原文出處:http://coolshell.cn/articles/4907.html
在函數外存取局部變量的一個比喻 作者:2011年6月28日
在StackOverflow上一這樣一個關於C/C++的問題,問問題的人給了一個代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int
* foo() { int
a = 5; return
&a; } int
main() { int * p = foo(); cout << *p; *p = 8; cout << *p; } |
你可以編譯並運行這個代碼(編譯時會有一個Warning),結果是:5 8。看上去你可以存取一個函數內的局部變量。但這和我們理解的不一樣——函數內的變量在函數退出時就被釋放了,不應該在外部還可以被引用。當然,對於C/C++熟悉的人都知道其實並不是真正的釋放,你依然還可以通過內存地址去進行操作,這是C/C++的內存管理的不安全性——指針可以用來亂指。
這個問題的解答是比較簡單的,但是這個問題有一個答案中的比喻非常精彩。這個比喻是這樣的——
你在某個酒店訂了一個房,你入住的時候,你放了一本書在這個酒店的抽屜裏,但是你走的時候,你忘了這本書。而且,你還沒有把這個房間的鑰匙還回去。於是,你在未來某個時候,偷偷地回來,打開這個房間的門,你看到了你的書還在裏間。當然,還還可以放回別的書。因爲,這個酒店管理不會在你走的時候把你留下的書清走,而且,這個酒店的管理的安保措施不是那麼嚴格,因爲他信任每一個客人都會遵守管理條例。
在這種情況下,如果你幸運的話,書還會在那裏,也可能你的書已經沒了。也有可能當你回去的時候,有一個人在那裏正在撕你的書,或者酒店把那個抽屜都挪走並變成衣櫃,或是整個酒店正在被拆除以改成了一個足球場,而你偷偷摸摸進到施工現場的時候被炸死。
真是很精彩的比喻。這就是C/C++的不安全的地方,也正是Linus說的,C++是一門恐怖的語言是因爲有很多不合格的程序員在使用它。就像你看到小孩子玩火一樣的恐怖。
關於這個事,還有一個比較經典的示例如下—— 函數a的初始化會影響函數b的數組。注意函數a中的 volatile
關鍵字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <iostream> using
namespace std; void
a() { volatile
int array[10]; for
( int
i = 0; i < 10; i++) array[i] = i; } void
b() { int
array[10]; for
( int
i = 0; i < 10; i++) cout << array[i]; } int
main() { a(); b(); } |
真是可愛的C/C++。