首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在基于范围的for循环中获取无效引用。

在基于范围的for循环中获取无效引用。
EN

Stack Overflow用户
提问于 2015-04-10 21:56:57
回答 3查看 700关注 0票数 0
代码语言:javascript
复制
auto& kphist = this->kphist;
for (auto& it : kphist) {

    it.second.aging(); // EXC-BAD-ACCESS
    if(it.second.age > LAST_DAY){
        kphist.erase(it.first);
        continue;
    }

}

kphist是私人成员。

代码语言:javascript
复制
Class A{
private:
    unordered_map<int, KeyPointHistory> kphist;
} 

调试器显示kphist中的所有项都是有效的,如何在for循环中出现错误引用。什么可能会出错?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-10 22:22:26

std::unordered_map::erase():对擦除元素的引用和迭代器无效。其他迭代器和引用不会失效。因此,不能在for循环的范围内使用std::unordered_map::erase() (因为这将尝试增加无效的迭代器)。

为了避免递增无效的迭代器,您可以先增量,然后使用原始迭代器擦除:

代码语言:javascript
复制
for(auto i=map.begin(),end=map.end(); i!=end; ) { // no increment here
  auto it=i++;                                    // but here instead
  if(must_remove(it))
    map.erase(it);
}

实际上,由于erase()将迭代器返回给下一个元素,您可以避免额外的迭代器it (感谢Hurkyl在注释中指出了这一点):

代码语言:javascript
复制
for(auto i=map.begin(),end=map.end(); i!=end; ) { // no increment here
  if(must_remove(i))
    i = map.erase(i);                             // but here 
  else
    ++i;                                          //  or here instead
}

不需要列出要删除的元素的列表.

顺便说一句,为什么不使用std::map (而不是std::unordered_map),因为您的密钥是int (这很容易订购)。另外,为什么要对同名的成员变量进行引用kphist

票数 5
EN

Stack Overflow用户

发布于 2015-04-10 22:04:49

您不能在遍历内容/迭代器时擦除它,您也不应该这样做。

将元素索引保存在不同的容器中,完成后循环遍历,然后删除所得到的元素。

什么可能会出错?

所有的一切!

票数 2
EN

Stack Overflow用户

发布于 2015-04-10 23:45:17

您可以通过直接将迭代器传递到要删除的项从unordered_map中擦除。当您这样做时,erase()返回后续的迭代器,所以您可以这样做:

代码语言:javascript
复制
for (auto pos = kphist.begin(); pos != kphist.end(); ) {
       it.second.aging();
       if(it.second.age > LAST_DAY)
           pos = kphist.erase(it); 
       else
           ++pos;
}

作为奖励,这可能比传递要擦除的键要快一些--因为你提供了迭代器,它可以直接到达要删除的项,而不是重新散列键以找到您已经知道的位置。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29571290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档