首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在修改容器时适当地迭代容器?

如何在修改容器时适当地迭代容器?
EN

Stack Overflow用户
提问于 2020-01-09 15:21:01
回答 2查看 607关注 0票数 3

我想在迭代容器时修改它。但是第一个版本的代码没有正常工作。谁能解释一下原因吗?

代码语言:javascript
运行
复制
// version 1
int main(){
    int a=1, b=2, c=5;
    std::set<int*> m = {&a, &b, &c};

    for(auto mi : m){
        std::cout << *mi << std::endl;
        m.erase(mi);
    }
}

然后我尝试了另一个版本。好像挺好的。当我这样迭代的时候有什么潜在的麻烦吗?

代码语言:javascript
运行
复制
// version 2
int main(){
    int a=1, b=2, c=5;
    std::set<int*> m = {&a, &b, &c};

    while (!m.empty()){
        std::cout << **m.begin() << std::endl;
        m.erase(m.begin());
    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-09 15:25:11

看看std::set::erase的文档

对擦除元素的

引用和迭代器无效。

这就不足为奇了。

现在,想想基于范围的for循环是什么意思:

代码语言:javascript
运行
复制
auto && range = range_expression ;
for (auto begin = begin_expr, end = end_expr; begin != end; ++begin) {
    range_declaration = *begin;
    loop_statement
}

注意当前元素的迭代器是如何通过循环增量在迭代之后使用的。递增无效迭代器的行为未定义。

在第二个循环中,您总是通过调用std::set::begin获得一个有效的迭代器。

在这种情况下,在迭代时修改容器是没有意义的。编写一个循环以打印所有元素,然后调用clear以获得相同的结果。

通常,对于特定情况有一种更简单的方法,如上面所描述的,但如果没有,通常在迭代时修改容器的正确方法是不使用范围,而是使用显式迭代器循环,并使用操作的结果(无论是擦除还是插入)作为下一个迭代器值,而不是增加现在无效的迭代器。

票数 6
EN

Stack Overflow用户

发布于 2020-01-09 15:43:10

我不认为第二个解决方案有什么问题,您可以使用set iterator

代码语言:javascript
运行
复制
#include <iostream>
#include <set>

using namespace std;

int main(){
    int a=1, b=2, c=5;
    set<int*> m = {&a, &b, &c};
    set<int*>::iterator it = m.begin();

    while(it != m.end()){
        cout << **it << endl;
        it = m.erase(it);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59667104

复制
相关文章

相似问题

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