c++ - 序列容器的重新分级删除功能

标签 c++ stl

下面的文字是 Effective STL Item 9 的片段

ofstream logFile; // log file to write to
AssocContainer<int> c;
…
for (AssocContainer<int>::iterator i = c.begin(); // loop conditions are the
     i !=c.end();){ //same as before
     if (badValue(*i)){
         logFile << "Erasing " << *i <<'\n'; // write log file
         c.erase(i++); // erase element
      }
      else ++i;
} 

现在给我们带来麻烦的是 vector、string 和 deque。我们不能再使用 erase-remove 习惯用法了,因为没有办法通过 erase 或 remove 来写入日志文件。此外,我们不能使用刚刚为关联容器开发的循环,因为它会为 vector 、字符串和双端队列产生未定义的行为!回想一下,对于这样的容器,调用 erase 不仅会使指向被删除元素的所有迭代器无效,还会使被删除元素之外的所有迭代器无效。在我们的例子中,这包括 i 之外的所有迭代器。我们编写 i++、++I 或您能想到的任何其他内容都没关系,因为生成的迭代器均无效。

我们必须对 vector 、字符串和双端队列采取不同的策略。特别是,我们必须利用 erase 的返回值。该返回值正是我们所需要的:它是一个有效的迭代器,一旦完成删除,它就会指向被删除元素之后的元素。换句话说,我们这样写:

for (SeqContainer<int>::iterator i = c.beqin();
       i != c.end();){
       if (badValue(*i)){
          logFile << "Erasing " << *i << '\n';
          i = c.erase(i); // keep i valid by assigning
       } //erase's return value to it
       else ++i;
}

我的问题是作者提到如果我们在 vector 、字符串、双端队列上使用删除“使所有指向被删除元素的迭代器无效,它也使所有超出被删除元素的迭代器无效”,但如果我们使用返回值,后面的语句是矛盾的erase 之后我们就可以使用它了,问题:“erase 不是使所有超出已删除元素的指针无效吗?

最佳答案

Question: "Isn't erase invalidate all pointer beyond erased element?

可能会,但在这种情况下与您无关。 erase() 可能会使在调用 erase() 之前获得的现有迭代器无效,但是 erase() 本身返回的是一个新的、有效的任何情况下的迭代器。

关于c++ - 序列容器的重新分级删除功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47575760/

相关文章:

c++11 - 在具有 protected 析构函数的类中使用 unique_ptr

C++ 严格弱排序派生类

c++ - 将类似数组的对象作为模板值参数

C++模仿ls之类的命令

c++ - 本地类变量位置

c++ - 如何在一个类中同时运行某些东西(在单线程平台中)?

c++ - sizeof() 运算符在 C++ 中做什么

c++ - 为什么大多数STL算法都需要排序后的数据作为输入?

c++ - Qt库,子类窗口拦截消息?

c# - C# 通用委托(delegate)的 C++ 等效语法,以及与 lambda 的用法