0

我在单独的数据结构中维护一组多集容器的迭代器。过了一会儿,我从这个数据结构中选择了一个迭代器,然后从多重集中删除了与该迭代器相关的元素。我首先使用这样的东西:

#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;
}
4

2 回答 2

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

但是,老实说,我无法想象这种情况实际上可能有用,或者更确切地说,是必需的。

于 2013-02-13T04:18:20.097 回答
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';
于 2013-02-14T02:05:23.017 回答