c++ - 删除 std::multiset 中的元素导致不相关的迭代器无效

标签 c++ c++11

<分区>

#include<set>
std::multiset<int>s;
int main() {
    s.insert(1);
    s.insert(2);
    s.insert(3);
    for (auto i=s.rbegin();i!=s.rend();++i) {
        auto j=s.lower_bound(*i<<1);
        if (j!=s.end())s.erase(j);
    }
}

这个程序崩溃了,我收到一条错误消息“map/set iterator not decrementable”。我想既然所有元素都是正整数,那么*i<<1将大于 *i ,因此 j 的指向位置将不同于 i .并根据reference :

References and iterators to the erased elements are invalidated. Other references and iterators are not affected.

由于i的指向位置和 j不同,删除j不会影响i和循环。所以我很困惑为什么它是错误的。

环境:Windows10 x86,Visual Studio 2015 Update 3

最佳答案

迭代器无效的原因是你的循环把它擦掉了,后面的for迭代是在循环的增量部分使用无效的迭代器。

如果你使用调试器运行它,你会看到当 erase()被调用时,迭代器 i指向与迭代器相同的元素 j .你现在s.erase(j) , 和 i也作废。关于++i在循环迭代中,尝试递增无效迭代器,因此出现错误。

s.insert(1);
s.insert(2);
s.insert(3);
for (auto i = s.rbegin(); i != s.rend(); 
     ++i) // <-- It's this that is causing the issue
{
    auto j = s.lower_bound(*i << 1);
    if (j != s.end())
        s.erase(j);  // <-- If `i` is pointing to this element, iteration becomes invalidated
}

所以基本上,您正在尝试执行 ++在不存在的东西上。由于您使用的是 Visual Studio(按照给出的错误进行),如果您在调试时转到程序集窗口,您会看到它确实是 ++。触发错误的操作。


请参阅迭代器失效:multiset::erase并在链接中注意这一点:

对已删除元素的引用和迭代器无效。

关于c++ - 删除 std::multiset 中的元素导致不相关的迭代器无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38407212/

相关文章:

c++ - 如何使用两个预编译头文件。一种用于托管代码,另一种用于非托管代码。 xxx.pch 不是有效的预编译头文件

c++ - 在 C++ 中查看析构函数

c++ - 返回值是类名后跟一对空括号是什么意思?

c++11 - C++11 何时给出有关运算符优先级的警告?

c++ - 为什么 emplace_back() 不使用统一初始化?

c++11 - Apple clang-703.0.29 如何在 C++1x 支持方面映射回 clang 版本?

c++ - 指针的返回 vector ——理解

c++ - 二进制运算符的类型为char和const char [2]的无效操作数

c++ - 可变模板的部分特化需要第一个非可变模板参数

c++11 - 可变模板函数的显式实例化