使用迭代器擦除STL multiset中的元素

时间:2013-02-13 04:16:33

标签: c++ data-structures stl multiset

我在一个单独的数据结构中维护一组多集合容器的迭代器。一段时间后,我从这个数据结构中选择一个迭代器,然后从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;
}

2 个答案:

答案 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';
相关问题