127

下面的代码表明,将 map as 传递给const方法operator[]会丢弃限定符:

#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
4

5 回答 5

173

std::map'soperator []未声明为const,并且不能归因于其行为:

T& 运算符[] (const Key& 键)

返回对映射到与 key 等效的 key 的 value 的引用,如果这样的 key 不存在,则执行插入。

结果,您的函数无法声明const,并使用地图的operator[].

std::mapfind()功能允许您在不修改地图的情况下查找密钥。

find()返回一个iterator, orconst_iterator到一个std::pair同时包含键 ( .first) 和值 ( .second) 的值。

在 C++11 中,您还可以使用at()for std::map。如果 element 不存在,则该函数将引发std::out_of_range异常,与operator [].

于 2008-11-04T18:37:03.777 回答
21

由于operator[]没有 const 限定的重载,它不能安全地用于 const 限定的函数。这可能是因为当前的重载是为了返回和设置键值而构建的。

相反,您可以使用:

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

或者,在 C++11 中,您可以使用at()运算符:

VALUE = map.at(KEY);
于 2014-01-23T22:28:02.950 回答
13

您不能operator[]在地图上使用,const因为该方法const不允许您修改地图(您可以分配给_map[key])。尝试改用该find方法。

于 2008-11-04T18:33:25.357 回答
7

一些较新版本的 GCC 标头(我的机器上的 4.1 和 4.2)具有非标准成员函数 map::at() ,它们被声明为 const 并在键不在映射中时抛出 std::out_of_range 。

const mapped_type& at(const key_type& __k) const

从函数注释中的引用来看,这似乎已被建议为标准库中的新成员函数。

于 2008-11-04T19:00:44.273 回答
0

首先,您不应该使用以 _ 开头的符号,因为它们是保留给语言实现/编译器编写者的。_map 很容易成为某人编译器上的语法错误,除了你自己,你没有人可以责备。

如果要使用下划线,请将其放在末尾,而不是开头。您可能犯了这个错误,因为您看到一些 Microsoft 代码这样做。请记住,他们编写了自己的编译器,因此他们可能能够摆脱它。即便如此,这也是个坏主意。

运算符 [] 不仅返回一个引用,它实际上在映射中创建条目。所以你不只是得到一个映射,如果没有,你正在创建一个。那不是你想要的。

于 2010-03-19T13:45:49.610 回答