插入不会永久更改地图?
问题描述:
我有这个类的成员变量是set<pair<string,map<string,int> > > setLabelsWords;
这是有点复杂,但忍受着我。在同一类的成员函数,我有以下代码:插入不会永久更改地图?
pair<map<string,int>::iterator,bool> ret;
for (auto j:setLabelsWords) {
if (j.first == label) {
for (auto k:words) {
ret = j.second.insert(make_pair(k,1));
if (ret.second == false) {
j.second[k]++;
}
}
}
}
“字”是一组字符串和“标签”是一个字符串。所以基本上它应该插入“k”(一个字符串),如果k已经在映射中,它会将int递增1。问题是它一直运行,直到最外层的for循环结束。如果我在最后一个括号之前打印j.second的大小,它会给我一个我期望的大小为13的大小,但是在最后一个括号之外,大小可以回到7,这就是该代码在映射之前的最初大小块运行。我非常困惑,为什么会发生这种情况,任何帮助都将非常感谢。
答
for (auto j:setLabelsWords) {
此迭代容器由值。这是同样的事情,如果你这样做:
class Whatever { /* something in here */ };
void changeWhatever(Whatever w);
// ...
{
Whatever w;
changewhatever(w);
}
无论changewhatever
确实给w
,任何修改作出,是的w
副本所做的,因为它被按值传递,给函数。
为了正确地更新你的容器,必须参考迭代:
for (auto &j:setLabelsWords) {
答
for (auto j:setLabelsWords) {
这产生了复制每个元件的。您在j
上执行的所有操作都会影响该副本,而不是setLabelsWords
中的原始元素。
通常情况下,你只用一个参考:
for (auto&& j:setLabelsWords) {
然而,由于std::set
的性质,这会不会让你走得很远,因为std::set
的元素不能被随意修改通过迭代器或对元素的引用,因为这将允许您创建一个包含重复项的集合。编译器不会允许。
这里是一个务实的解决方案:使用std::vector
代替std::set
:
std::vector<std::pair<std::string, std::map<std::string,int>>> setLabelsWords;
然后,您将能够使用参考方法进行了说明。
如果您需要std::set
小号元素的独特性,后来排序功能,您可以在std::vector
从std::vector
适用std::sort
和/或std::unique
,或创建一个新std::set
“。
啊我明白了!后续问题q:编译器现在抛出一个错误,因为由于某种原因它将j.second视为一个常量,所以我无法用insert或[]修改它。有没有解决的办法? – newtothis
看起来你的容器是'std :: set'。一组中的值不能修改。毕竟,一个集合命令它的内容,并且修改集合中的值可能会改变其内容的相对顺序,因此设置的值是const。使用不同的容器。关于容器的好处是它们的统一方法,所以你的代码不会需要任何改变。只需切换容器。 –