为什么我不能使用 std::map[ ] 添加字符串,但 std::map.at() 有效?
Why I can't use the std::map[ ] to add a string, but std::map.at() works?
我的问题是为什么 s += t.getM()[0];在示例代码中 raise
main.cpp:44:20: error: passing ‘const std::map >’ as ‘this’ argument discards qualifiers [-fpermissive]
我检查了 cppreference,它说 return 都是参考。
此外,为什么 operator[] 和 .at() 都适用于 std::vector?
示例代码在这里。
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
class test {
public:
test(string str) {
vec.push_back(str);
mp[0] = str;
}
const vector<string>& getV() const {
return vec;
}
const map<int, string>& getM() const {
return mp;
}
private:
vector<string> vec;
map<int, string> mp;
};
int main()
{
string s;
test t("hello ");
s += t.getV().at(0);
s += t.getV()[0];
s += t.getM().at(0);
s += t.getM()[0];
cout << s;
}
std::map::operator[]
仅适用于非 const
std::map
。 The documentation on std::map::operator[]
很好地解释了这一点。这是页面开头的摘录:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
如您所见,如果键不存在,它会在映射中插入一个新的 key/value 对。显然,这不适用于 const
映射,因为您不能向其中插入元素,因为它们是不可变的。为什么没有 const
不会创建新值的运算符重载,我不知道。但就是这样。
std::map::at()
,但并不完全像 std::map::operator[]
。同样,摘自 documentation of std::map::at()
:
Returns a reference to the mapped value of the element with key equivalent to key. If no such element exists, an exception of type std::out_of_range
is thrown.
此外,该函数也有一个 const
重载:const T& at(const Key& key) const;
因此它可以用于 const
映射。
In addition, why both operator[] and .at() work for std::vector?
因为 std::vector::operator[]
and std::vector::at()
的工作方式非常相似,除了 std::vector::at()
进行边界检查而 std::vector::operator[]
不进行边界检查。两者都不会创建新值(因为那不是向量的工作方式)并且都具有 const
重载。事实上,std::vector::operator[]
的文档甚至解决了它与 std::map::operator[]
:
之间的区别
Unlike std::map::operator[]
, this operator never inserts a new element into the container. Accessing a nonexistent element through this operator is undefined behavior.
(这是未定义的行为,因为正如我之前提到的,operator[]
不进行边界检查。)
只是添加到,下面增加容器的大小:
class test {
public:
...
map<int, string>& getM() {
return mp;
}
private:
...
}
int main()
{
string s;
test t("hello ");
s += t.getV().at(0);
s += t.getV()[0];
s += t.getM().at(0);
s += t.getM()[0];
cout << s;
cout << t.getM().size() << endl; // prints 1
auto temp = t.getM()[1]; // Key=1 does not exist in the container and hence is added
cout << t.getM().size() << endl; // prints 2
}
另外,我从 clang 而不是 gcc 得到了关于这个问题的更好提示:
no viable overloaded operator[] for type 'const map<int, std::string>' (aka 'const map<int, basic_string<char> >')
我的问题是为什么 s += t.getM()[0];在示例代码中 raise
main.cpp:44:20: error: passing ‘const std::map >’ as ‘this’ argument discards qualifiers [-fpermissive]
我检查了 cppreference,它说 return 都是参考。
此外,为什么 operator[] 和 .at() 都适用于 std::vector?
示例代码在这里。
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
class test {
public:
test(string str) {
vec.push_back(str);
mp[0] = str;
}
const vector<string>& getV() const {
return vec;
}
const map<int, string>& getM() const {
return mp;
}
private:
vector<string> vec;
map<int, string> mp;
};
int main()
{
string s;
test t("hello ");
s += t.getV().at(0);
s += t.getV()[0];
s += t.getM().at(0);
s += t.getM()[0];
cout << s;
}
std::map::operator[]
仅适用于非 const
std::map
。 The documentation on std::map::operator[]
很好地解释了这一点。这是页面开头的摘录:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
如您所见,如果键不存在,它会在映射中插入一个新的 key/value 对。显然,这不适用于 const
映射,因为您不能向其中插入元素,因为它们是不可变的。为什么没有 const
不会创建新值的运算符重载,我不知道。但就是这样。
std::map::at()
,但并不完全像 std::map::operator[]
。同样,摘自 documentation of std::map::at()
:
Returns a reference to the mapped value of the element with key equivalent to key. If no such element exists, an exception of type
std::out_of_range
is thrown.
此外,该函数也有一个 const
重载:const T& at(const Key& key) const;
因此它可以用于 const
映射。
In addition, why both operator[] and .at() work for std::vector?
因为 std::vector::operator[]
and std::vector::at()
的工作方式非常相似,除了 std::vector::at()
进行边界检查而 std::vector::operator[]
不进行边界检查。两者都不会创建新值(因为那不是向量的工作方式)并且都具有 const
重载。事实上,std::vector::operator[]
的文档甚至解决了它与 std::map::operator[]
:
Unlike
std::map::operator[]
, this operator never inserts a new element into the container. Accessing a nonexistent element through this operator is undefined behavior.
(这是未定义的行为,因为正如我之前提到的,operator[]
不进行边界检查。)
只是添加到
class test {
public:
...
map<int, string>& getM() {
return mp;
}
private:
...
}
int main()
{
string s;
test t("hello ");
s += t.getV().at(0);
s += t.getV()[0];
s += t.getM().at(0);
s += t.getM()[0];
cout << s;
cout << t.getM().size() << endl; // prints 1
auto temp = t.getM()[1]; // Key=1 does not exist in the container and hence is added
cout << t.getM().size() << endl; // prints 2
}
另外,我从 clang 而不是 gcc 得到了关于这个问题的更好提示:
no viable overloaded operator[] for type 'const map<int, std::string>' (aka 'const map<int, basic_string<char> >')