2013-02-08 66 views
-1

我從php我,當我定義是這樣的:爲什麼我在使用未定義索引時沒有收到錯誤?

$a = array(); 
echo $a[586]; 

我會得到一個有關未定義指數另行通知。

同時在c++我可以這樣做:

map<int, string> my_map; 
cout << "Map is: " << my_map[34535]; 

string sentence = "acdefb s"; 
cout << "Letter is: " << sentence[15]; 

而且我不會得到任何錯誤。

爲什麼不可能在php和可能在c++

+3

有趣的是,PHP的表現比C++更嚴格。 – 2013-02-08 20:48:57

+1

在C++'operator [](keytype)中,如果map中沒有一個已經存在,那麼map *將會添加一個默認構造的map的value-type實例。如果你不想要這種行爲,可以使用'.find(keytype)'來代替'my_map.end()'來檢查生成的迭代器。 – WhozCraig 2013-02-08 20:49:18

+1

'句子[34535]'超出界限,並會導致程序崩潰。 – Rapptz 2013-02-08 20:50:41

回答

7

因爲PHP和C++是兩種截然不同的語言,它們具有完全不同的語義。在C++中將[]運算符與std::map對象一起使用時,如果密鑰尚未存在於映射中,則會將新元素插入到映射中。在PHP中,情況並非如此。

關於你與std::string sentance秒例如,它是有效使用[]操作者與C中的std::string ++無效索引(索引是>= sentance.length())。您可能不會收到任何「錯誤」,因爲使用與std::string無效索引的結果是undefined behavior,這意味着任何事情都可能發生。現代平臺上的一個常見結果是「分段錯誤/訪問衝突」,通常會導致程序崩潰。

使用std::string如果要防止未定義的行爲,可以使用std::string::at()而不是[]運算符。如果使用無效索引,at函數會執行邊界檢查並引發std::out_of_range

0

將字符串索引爲大於字符串長度的值幾乎總是會導致分段錯誤。如果這段代碼實際上在沒有錯誤的情況下運行,那是因爲'幸運的是'這個內存地址不能解析爲不屬於進程的東西。相反,你只會得到垃圾。

3

C++是一種爲提高性能而編寫的語言。如果您擁有一個擁有1000萬件物品的陣列,併合法地遍歷所有物品,則會增加時間來檢查這10M接入點中的每一個是否有效。作爲一個副作用,你也可以在「正確」的情況下走出有效範圍,而不會被發現。最有可能的是,如果你在有效範圍之外太遠,SOMETHING會出錯。但是C++並不能保證它確實出錯或者會發生什麼 - 這就是所謂的「未定義行爲」 - 簡稱UB。

在地圖的情況下,它不會做你認爲它會做的事情,它實際上在你的容器中創建一個新的空元素,然後打印它。

因此,如果您有「未知」索引 - 例如將索引作爲參數的函數,最好檢查該值是否在範圍內 - 至少在代碼的調試版本中。您可以使用例如assert()做到這一點:

// v is a vector, or string, or some such. 
assert(index < v.size); 

這將「打破」你的節目你去超出有效範圍的任何時間。在發佈版本中,assert編譯爲無,因此在正確的發行版本中運行代碼時沒有額外的代碼。

相關問題