为了账号安全,请及时绑定邮箱和手机立即绑定

迭代时从STL集中删除元素

迭代时从STL集中删除元素

C++
江户川乱折腾 2019-10-15 15:49:33
我需要遍历一组并删除符合预定义条件的元素。这是我编写的测试代码:#include <set>#include <algorithm>void printElement(int value) {    std::cout << value << " ";}int main() {    int initNum[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };    std::set<int> numbers(initNum, initNum + 10);    // print '0 1 2 3 4 5 6 7 8 9'    std::for_each(numbers.begin(), numbers.end(), printElement);    std::set<int>::iterator it = numbers.begin();    // iterate through the set and erase all even numbers    for (; it != numbers.end(); ++it) {        int n = *it;        if (n % 2 == 0) {            // wouldn't invalidate the iterator?            numbers.erase(it);        }    }    // print '1 3 5 7 9'    std::for_each(numbers.begin(), numbers.end(), printElement);    return 0;}最初,我认为在迭代过程中从集合中删除一个元素会使迭代器无效,并且for循环的增量将具有未定义的行为。即使我执行了此测试代码,但一切顺利,并且我无法解释原因。我的问题: 这是标准集的已定义行为还是此实现特定?顺便说一下,我在ubuntu 10.04(32位版本)上使用gcc 4.3.3。谢谢!
查看完整描述

3 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

如果通过valgrind运行程序,则会看到许多读取错误。换句话说,是的,迭代器是无效的,但是您在示例中很幸运(或者真的很不幸,因为您没有看到未定义行为的负面影响)。一种解决方案是创建一个临时迭代器,增加温度,删除目标迭代器,然后将目标设置为温度。例如,重新编写循环,如下所示:


std::set<int>::iterator it = numbers.begin();                               

std::set<int>::iterator tmp;                                                


// iterate through the set and erase all even numbers                       

for ( ; it != numbers.end(); )                                              

{                                                                           

    int n = *it;                                                            

    if (n % 2 == 0)                                                         

    {                                                                       

        tmp = it;                                                           

        ++tmp;                                                              

        numbers.erase(it);                                                  

        it = tmp;                                                           

    }                                                                       

    else                                                                    

    {                                                                       

        ++it;                                                               

    }                                                                       


查看完整回答
反对 回复 2019-10-15
?
蛊毒传说

TA贡献1895条经验 获得超3个赞

您误解了“不确定行为”的含义。未定义的行为并不表示“如果执行此操作,则程序崩溃或产生意外的结果。” 这意味着“如果这样做,程序可能会崩溃或产生意外结果”,或执行其他任何操作,具体取决于您的编译器,操作系统,月相等。

如果某件事情执行时没有崩溃并且表现出预期的效果,则不能证明它不是未定义的行为。它所证明的是,在特定操作系统上使用特定编译器进行编译后,其行为恰好符合该特定运行所观察到的。

从集合中删除元素会使迭代器对已删除元素无效。使用无效的迭代器是未定义的行为。碰巧的是,观察到的行为正是您在此特定情况下想要的;这并不意味着该代码是正确的。


查看完整回答
反对 回复 2019-10-15
  • 3 回答
  • 0 关注
  • 471 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信