在StackOverflow上一這樣一個關於C/C++的問題,問問題的人給了一個代碼如下:
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 關鍵字。
#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();
}