通过访问器功能使用重载的operator []

时间:2012-05-01 18:31:17

标签: c++ operator-overloading accessor

我有一个访问器函数,它返回对类型(std :: map)的... ...

的const引用
myMap_t const& getMap() const {return paramMap;} 

该类型有一个重载[]运算符。然后,以下面的方式直接从getter函数使用[]运算符的语法是什么,但实际上有效。

parameter = contextObj.getMap()[key];

错误信息是:

context.cpp:35: error: passing   
  'const std::map<
     std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
     float, 
     std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, 
     std::allocator<std::pair<
       const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
       float> > >'
as 'this' argument of 
  '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&)  
with 
  _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
  _Tp = float, 
  _Compare = std::less<std::basic_string<char, std::char_traits<char>,  td::allocator<char> > >, 
  _Alloc = std::allocator<std::pair<
    const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
    float> >]' 
discards qualifiers

4 个答案:

答案 0 :(得分:6)

问题是地图中的operator[]是一个变异操作,你不能在对地图的const引用上调用它。它变异的原因是它必须返回对值的引用,为此,如果密钥尚未存在于容器中,它将插入由该键寻址的新的默认构造值并返回对它的引用

如果您有const引用,并且想要确定元素是否存在(或访问它),则必须使用将返回迭代器的std::map<>::find。如果元素不存在,迭代器的值将为m.end()

答案 1 :(得分:3)

您通过const引用返回std::map,但std::map::operator[]不是const函数,因为有时需要更改映射。
要解决此问题,您应该执行以下操作之一:
(A)使用.find代替[]

auto iter = contextObj.getMap().find( key );
if (iter != contextObj.getMap().end())
    param = iter->second;

(B)将地图返回为非const(不推荐)
(C)制作包装类(大部分时间都不值得)

答案 2 :(得分:1)

您从方法const myMap_t&返回getMap()。从您的错误消息myMap_tstd::map的typedef。 operator[]的{​​{1}}需要一个可修改的对象(不能在const上调用),因为它可以将项插入到映射中(如果不存在具有指定键的项,则它将一个插入到映射并返回对该引用的引用)。 要解决这个问题,您有两种选择:

  • 使用std::map代替contextObj.getMap().find(key)获取元素的迭代器(如果不存在,则使用contextObj.getMap()[key]
  • 返回map.end()(不带const)以获取可调用myMap_t&的可修改对象

答案 3 :(得分:1)

context.cpp:35: error: passing   
  'const std::map<
     std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
     float, 
     std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, 
     std::allocator<std::pair<
       const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
       float> > >'
as 'this' argument of 
  '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&)  
with 
  _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
  _Tp = float, 
  _Compare = std::less<std::basic_string<char, std::char_traits<char>,  td::allocator<char> > >, 
  _Alloc = std::allocator<std::pair<
    const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
    float> >' 
discards qualifiers

std::basic_string是用于实现std::string的模板,实际上std::string只是基于char的实例化。所以首先替换它:

context.cpp:35: error: passing   
  'const std::map<
     std::string, 
     float, 
     std::less<std::string>, 
     std::allocator<std::pair<const std::string, float> >
  >'
as 'this' argument of 
  '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&)  
with 
  _Key = std::string,
  _Tp = float, 
  _Compare = std::less<std::string>, 
  _Alloc = std::allocator<std::pair<const std::string> >' 
discards qualifiers

我们并不关心地图的_Compare(比较函数)和_Alloc(分配器)参数,因为我们只是使用默认值;所以让我们忽略这些,让我们也将_Key_Tp值替换为模板描述:

context.cpp:35: error: passing   
  'const std::map<std::string, float>'
as 'this' argument of 
  'float& std::map<std::string, float>::operator[](const std::string&)  
discards qualifiers

我们走了,简单得多。我们正在使用operator[]的{​​{1}},我们正试图在std::map<std::string, float>上使用它(也就是说,这就是我们用作const std::map<std::string, float>参数的内容为了电话)。这会“丢弃限定符”,特别是this限定符。

编译器告诉您地图的const不承诺保留地图operator[],即允许更改地图。这是一个编译错误,因为代码是用内置断言编写的,地图不会改变。

地图为什么会改变?好吧,看看文档:

  

如果x匹配容器中元素的键,则该函数返回对其映射值的引用。

     

如果x与容器中任何元素的键不匹配,则函数将使用该键插入新元素,并返回对其映射值的引用。请注意,即使没有为元素指定映射值(使用其默认构造函数构造元素),这也会始终将映射大小增加1。

(强调我的)。

插入元素肯定是一种修改。

为什么这样做?好吧,we already have a question for that