为什么STL映射的[]运算符不是?

时间:2009-09-25 00:45:09

标签: c++ const

为了这个问题,举例说明:

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map[x] << std::endl
}

这不会编译,因为[]运算符是非const的。

这很不幸,因为[]语法看起来非常干净。相反,我必须做这样的事情:

void MyClass::MyFunction( int x ) const
{
  MyMap iter = m_map.find(x);
  std::cout << iter->second << std::endl
}

这一直困扰着我。为什么[]运算符是非const?

6 个答案:

答案 0 :(得分:82)

对于std::mapstd::unordered_map,如果以前不存在,operator[]会将索引值插入到容器中。这有点不直观,但就是这样。

由于必须允许它失败并插入默认值,因此不能在容器的const实例上使用该运算符。

http://en.cppreference.com/w/cpp/container/map/operator_at

答案 1 :(得分:47)

现在,使用C ++ 11,您可以使用at()

获得更清晰的版本
void MyClass::MyFunction( int x ) const
{
  std::cout << m_map.at(x) << std::endl;
}

答案 2 :(得分:27)

新读者注意事项 最初的问题是关于STL容器(不是特别关于std :: map)

应该注意的是,大多数容器上都有一个const版本的operator [] 只是std :: map和std :: set没有const版本,这是实现它们的底层结构的结果。

来自std :: vector

reference       operator[](size_type n) 
const_reference operator[](size_type n) const 

另外,对于您的第二个示例,您应该检查是否找不到该元素。

void MyClass::MyFunction( int x ) const
{
    MyMap iter = m_map.find(x);
    if (iter != m_map.end())
    {
        std::cout << iter->second << std::endl
    }
}

答案 3 :(得分:3)

由于operator []可能会在容器中插入新元素,因此它不可能是const成员函数。注意,operator []的定义非常简单:m [k]等价于(*((m.insert(value_type(k,data_type())))。first))。second。严格来说,这个成员函数是不必要的:它只是为了方便而存在

答案 4 :(得分:0)

索引运算符应该只是一个只读容器的const(STL本身并不存在)。

索引运算符不仅用于查看值。

答案 5 :(得分:-1)

如果声明std :: map成员变量是可变的

mutable std::map<...> m_map;

您可以在const成员函数中使用std :: map的非const成员函数。