插入不会永久更改地图?

insert doesn't permanently change map?

本文关键字:地图 插入      更新时间:2023-10-16

我有一个 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递增。问题是它有效,直到循环最外面的循环结束为止。如果我在最后一个支架之前打印出J.Second的大小,它将给我一个我期望13的尺寸,但是在最后一个括号之外,大小又回到了7个,这是地图的大小最初是在此代码之前的。块运行。我非常困惑为什么会发生这种情况,并感谢任何帮助。

for (auto j:setLabelsWords) {

通过Value ,通过容器迭代。这与您一样:

class Whatever { /* something in here */ };
void changeWhatever(Whatever w);
// ...
{
   Whatever w;
   changewhatever(w);
}

changewhateverw做的任何修改,无论是对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::sort和/或std::unique,或在std::vector的元素中创建新的std::set