插入不会永久更改地图?

时间:2017-04-17 11:09:40

标签: c++ binary-search-tree

我有一个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]++;
      }
    }
  }
}

&#34;也就是说&#34;是一组字符串和&#34;标签&#34;是一个字符串。所以基本上它应该插入&#34; k&#34; (一个字符串)并且如果k已经在地图中,它将int递增1.问题是它是有效的,直到最外面的for循环结束。如果我在最后一个括号之前打印j.second的大小,它会给我一个我期望的大小为13的大小,但是在最后一个大括号之外,大小会回到7,这就是地图的大小是最初在此代码块运行之前。我非常困惑,为什么会发生这种情况,我们非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

for (auto j:setLabelsWords) {

这会按容器 按值 进行迭代。这与你做的一样:

class Whatever { /* something in here */ };

void changeWhatever(Whatever w);

// ...

{
   Whatever w;

   changewhatever(w);
}

无论changewhateverw做了什么,无论做了什么修改,都会对w的副本进行修改,因为它会通过值传递给函数。

为了正确更新容器,您必须按引用进行迭代:

for (auto &j:setLabelsWords) {

答案 1 :(得分:2)

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::sort上应用std::unique和/或std::vector,或者创建新{来自std::set元素的{1}}。

相关问题