我在一个单独的数据结构中维护一组多集合容器的迭代器。一段时间后,我从这个数据结构中选择一个迭代器,然后从multiset中删除相关元素到该迭代器。我首先使用这样的东西:
#include <iostream>
#include <set>
int main ()
{
std::multiset<int> myints;
std::cout << "0. size: " << myints.size() << '\n';
for (int i=0; i<10; i++) myints.insert(i);
std::cout << "1. size: " << myints.size() << '\n';
myints.insert (5);
std::cout << "2. size: " << myints.size() << '\n';
std::multiset<int>::iterator it = myints.find(5);
myints.erase (it);
std::cout << "3. size: " << myints.size() << '\n';
myints.erase (it);
std::cout << "4. size: " << myints.size() << '\n';
return 0;
}
然而,事实证明第二个myints.erase (it);
导致分段错误。因此,我更改为以下代码,它的工作原理。我想知道这是否是好的方法,或者它是可行的undefined
情况:
int main ()
{
std::multiset<int> myints;
std::cout << "0. size: " << myints.size() << '\n';
for (int i=0; i<10; i++) myints.insert(i);
std::cout << "1. size: " << myints.size() << '\n';
myints.insert (5);
std::cout << "2. size: " << myints.size() << '\n';
std::multiset<int>::iterator it = myints.find(5);
myints.erase (it);
std::cout << "3. size: " << myints.size() << '\n';
std::multiset<int>::iterator newit = myints.find(*it);
myints.erase (newit);
std::cout << "4. size: " << myints.size() << '\n';
return 0;
}
答案 0 :(得分:2)
erase(it)
使迭代器it
无效,即它在erase
之后无用,并且对它执行任何操作都会导致未定义的行为。 (当你指向的元素被删除时,你可能期望它“移动到下一个元素”,但这不是它所做的。)
你的第二种方法并没有解决这个问题。它可能是偶然的,但是在删除之后你仍然会重复使用it
。
编辑:鉴于您的描述“我想从多个集合中仅擦除一个5并在擦除后保持其有效以进行下一次擦除。”,您可以通过创建迭代器的副本来实现,递增原件,然后通过副本擦除:
it = myints.find(5);
// better add a check here to make sure there actually is a 5 ...
std::multiset<int>::iterator newit = it;
it++;
myints.erase(newit);
由于你已经增加了it
,它仍然有效,因为它没有指向被erase
杀死的元素。
但是,老实说,我无法想象这可能实际上有用,或者更确切地说是必需的情况。
答案 1 :(得分:0)
在第一种方法中,迭代器在删除迭代器指向的元素时会失效,稍后当您尝试使用相同的迭代器再次擦除时,会出现分段错误。
在你的第二种方法中,因为每次你在擦除后找到它都会给你正确的迭代器。
您可以通过在代码中进行以下更改来修复第一种情况。后增量运算符将返回一个新对象,并将迭代器移动到下一个位置。我还建议在擦除之前进行结束检查,否则可能会出现未定义的行为。
std::multiset<int>::iterator it = myints.find(5);
if(it != myints.end())
myints.erase (it++);
std::cout << "3. size: " << myints.size() << '\n';
if(it != myints.end())
myints.erase (it++);
std::cout << "4. size: " << myints.size() << '\n';