首页 >后端开发 >C++ >在迭代期间从'std::set”中删除元素是 C 中定义的行为还是特定于实现的行为?

在迭代期间从'std::set”中删除元素是 C 中定义的行为还是特定于实现的行为?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-12-04 08:30:14596浏览

Is Deleting Elements from a `std::set` During Iteration Defined Behavior in C   or Implementation-Specific?

在迭代期间从 std::set 中删除元素:实现影响

在删除元素时迭代集合可能会带来挑战,因为操作可能会使迭代器无效。在这种情况下,问题就出现了:这种行为是由 C 标准定义的还是特定于实现的?

实现依赖

根据 C 标准(23.1 .2.8),向集合中插入元素不应影响迭代器或对容器的引用,而擦除元素仅应使迭代器和对已删除元素的引用。然而,在擦除操作期间迭代器的行为并未明确指定,使其对特定于实现的决策开放。

GCC 实现

在提供的示例代码中,使用Ubuntu 10.04 上的 GCC 4.3.3 在迭代期间从集合中删除元素不会使迭代器失效。这表明 GCC 的实现遵循更宽松的方法,允许在擦除后继续使用迭代器。

符合解决方案

为了确保标准一致性,采用不同的方法是必须的。一种常见的解决方案是在擦除元素之前创建迭代器的副本:

for (auto it = numbers.begin(); it != numbers.end(); ) {
    if (*it % 2 == 0) {
        numbers.erase(it++);
    }
    else {
        ++it;
    }
}

在这种情况下,后缀增量(it)将旧位置传递给erase()函数,同时跳转到下一个元素。此处首选后缀增量,因为它避免了前缀增量可能出现的潜在双增量问题(当条件为 false 时)。

C 11 Update

With C 11 的出现,提供了更优雅的解决方案。现在,erase() 函数返回一个迭代器,指向最后一个删除的元素后面的元素(如果最后一个元素被删除,则返回 set::end)。这允许更简洁的实现:

for (auto it = numbers.begin(); it != numbers.end(); ) {
    if (*it % 2 == 0) {
        it = numbers.erase(it);
    }
    else {
        ++it;
    }
}

以上是在迭代期间从'std::set”中删除元素是 C 中定义的行为还是特定于实现的行为?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn