2011-11-29 30 views
6

我讀:爲什麼只有非常量映射才能提供像關聯數組一樣的直接元素檢索?

標準C++庫:教程和參考由尼古拉M. Jossuttis

這是我去到時我會使用一些STL機制預定任何重要的方式。無論如何,我很快就重讀了std :: map和相關算法的章節,並且我注意到了一個我之前沒有想過的句子:

非常量映射爲直接元素訪問提供了下標操作符。但是,下標運算符的索引不是元素的整數位置。 ...等。

爲什麼只有非常量映射可以像關聯數組一樣使用?在這種情況下,提供只讀語義似乎相當簡單。如果你試圖用一個不存在的鍵來檢索一個元素(假設你不能在地圖上添加一個新的鍵/值(如果它的常量不變)),那麼我認爲例外是可能的。

我想了解這背後的原因,如果任何人都可以擺脫一些光:)謝謝!

+0

如果沒有匹配的元素,你會如何期待map [「foo」]'在'std :: map'的const實例上工作?它不能創建它,因爲'map'是常量,拋出異常會與非const行爲有所不同,這可能是危險的。 – ereOn

回答

11

爲什麼只能非恆定的地圖關聯數組等 方式使用?

因爲那些運算符返回對與特定鍵關聯的對象的引用。如果容器中尚未包含這樣的對象,則插入默認對象。現在,如果容器是常量,則不能向其中插入任何對象,並且不能返回對不存在對象的引用,這就是爲什麼這些運算符僅適用於非常量容器。

當然,在這種情況下拋出異常是可能的,但不是當給定鍵的對象不存在時處理相當普通的情況的最佳方式。基本上,例外情況非常昂貴,適用於特殊情況,而上述情況並非如此,因此不值得。

更好的方法是返回一個迭代器,但用戶將不得不檢查它是否「結束」,這將使用例類似於調用find(),所以沒用。爲常量容器返回迭代器或指針也是可能的,但這會破壞語義並且令人困惑。

1

[] - 運算符變異容器:如果該鍵不存在,它將被創建:

return m[1];  // **creates** m[1] if it doesn't exist 

return *m.find(1) // UB if m[1] doesn't exist (dereferencing m.end()) 

此外,[]總是返回一個非恆定的參考,所以可以說m[1] = 2;。在另一方面,find()返回迭代其常量性是地圖本身的:

map_t m; 
*m.find(1) = 2; // Only OK if m[1] exists 
// *const_cast<map_t const &>(m).find(1) = 2; // error 
1

[]如果密鑰不存在,則運算符會修改該映射。

如果鍵不存在,映射將使用鍵創建一個新條目,併爲關聯值創建一個默認值,並返回其引用。要發生這種情況,operator[]必須是非const函數,這意味着它不能在const實例std::map上運行。

8

在C++ 11中,您可以使用at()來獲取「獲取映射值,否則拋出異常」行爲。重載operator[]做兩件事(即插入新的對或拋出)取決於一個映射是否是常量將會太混亂並且容易出錯。

相關問題