我有一个访问器函数,它返回对类型(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
答案 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_t
是std::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。