3

我有一个访问器函数,它返回对类型 (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

4 回答 4

6

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

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

于 2012-05-01T18:37:29.027 回答
3

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

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

(B) 将映射返回为非 const(不推荐)
(C) 制作一个包装类(大多数时候不值得)

于 2012-05-01T18:38:46.893 回答
1

const myMap_t&你从你的方法返回一个getMap()。从您的错误消息myMap_t中可以看出 a 的 typedef std::map。Ther operator[]ofstd::map需要一个可修改的对象(不能在 const 上调用),因为它可以将项目插入到地图中(如果不存在具有指定键的项目,它将向地图中插入一个并返回对该项目的引用)。要解决该问题,您有两种选择:

  • 使用contextObj.getMap().find(key)而不是contextObj.getMap()[key]获取元素的迭代器(或者map.end()如果它不存在)
  • 返回myMap_t&(不带 const)以获取可在其operator[]上调用的可修改对象
于 2012-05-01T18:39:15.820 回答
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(comparison function) 和_Alloc(allocator) 参数,因为我们只是使用默认值;所以让我们忽略这些,让我们也将_Keyand_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[]of our std::map<std::string, float>,并且我们正在尝试在 a 上使用它const std::map<std::string, float>(即,这就是我们用作this调用的参数的内容)。这“丢弃限定符”,特别是const限定符。

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

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

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

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

(强调我的)。

插入元素当然是一种修改。

为什么这样做?好吧,我们已经有一个问题了

于 2012-05-01T19:17:17.167 回答