2008-11-04 54 views
85

下面的代碼表示,地圖作爲const穿入operator[]方法丟棄限定符:C++地圖訪問丟棄限定符(常數)

#include <iostream> 
#include <map> 
#include <string> 

using namespace std; 

class MapWrapper { 
public: 
    const int &get_value(const int &key) const { 
     return _map[key]; 
    } 

private: 
    map<int, int> _map; 
}; 

int main() { 
    MapWrapper mw; 
    cout << mw.get_value(42) << endl; 
    return 0; 
} 

這是因爲其在地圖上的訪問發生可能的分配的?不能將地圖訪問函數聲明爲const?

MapWrapper.cpp:10: error: passing ‘const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >]’ discards qualifiers

+0

只是雞蛋裏挑骨頭,但MW可以簡單地聲明爲MapWrapper毫瓦; – luke 2008-11-04 18:40:04

+0

好點 - 我用幾種語言編寫,所以我傾向於規範它們之間的語法,所以它們都適合我的腦海。 :) – cdleary 2008-11-04 19:03:57

+0

我可以欣賞這一點。但要小心,在這種情況下,你有一個額外的對象構造和分配是不必要的。 – luke 2008-11-04 19:19:09

回答

118

std::map's operator [] is not declared as const, and cannot be due to its behavior:

Ť&操作符[](常量密鑰&鍵)

返回到被映射到鍵等同於鍵的值的基準,如果這樣的鍵尚不執行插入存在。

因此,您的功能不能被宣佈爲const,並使用地圖的operator[]

std::map's find()函數允許您在不修改地圖的情況下查找某個鍵。

find()返回iterator,或者const_iterator包含兩個密鑰(.first)和值(.second)的std::pair

在C++ 11中,您還可以使用at()代替std::map。如果元素不存在,則該函數會拋出std::out_of_range異常,與operator []不同。

10

不能使用operator []的一張地圖,是常量作爲方法不是const的,因爲它允許你修改地圖上(可以分配給_MAP [關鍵])。請嘗試使用find方法。

+1

作爲解釋:如果密鑰不存在,映射的運算符[]應該執行什麼操作?如果該映射是非常量的,則該鍵被添加了默認構造的值。如果映射const,operator []可以返回什麼?這個關鍵沒有價值。 – Arkadiy 2008-11-04 18:44:13

7

一些較新版本的GCC頭文件(我的機器上的4.1和4.2)具有非標準成員函數map :: at(),它們被聲明爲const,並且如果該鍵不在映射中,則拋出std :: out_of_range。

const mapped_type& at(const key_type& __k) const 

從該函數的評論中的引用看來,這似乎被建議作爲標準庫中的新成員函數。

0

首先,您不應該使用以_開頭的符號,因爲它們保留給語言實現/編譯器編寫器。 _map會成爲某人編譯器的語法錯誤,而且你自己也不會有人責怪。

如果你想使用下劃線,把它放在最後,而不是開始。你可能犯了這個錯誤,因爲你看到了一些微軟的代碼。請記住,他們編寫自己的編譯器,以便他們能夠擺脫它。即便如此,這是一個壞主意。

運算符[]不僅返回一個引用,它實際上會在地圖中創建條目。所以你不只是得到一個映射,如果沒有,你正在創建一個映射。這不是你想要的。

9

由於operator[]沒有const限定的重載,因此無法在const限定的函數中安全地使用它。這可能是因爲目前的超載是以返回和設置關鍵值爲目標而構建的。

相反,你可以使用:

VALUE = map.find(KEY)->second; 

,或者在C++ 11,你可以使用at()操作:

VALUE = map.at(KEY); 
相關問題