在列表迭代期间删除元素 - 安全

发布于 2024-08-19 13:06:20 字数 278 浏览 4 评论 0原文

我想知道这样的事情是否安全......

// Iterating through a <list>
while ( iter != seq.end()) {
  if ( test ) {
    iter = seq.erase( iter );
  } else {
    ++iter;
 }

我知道以这种方式迭代向量会使迭代器无效,但是同样的事情会发生在列表中吗?我认为不是,因为列表是通过指针连续的,而不是在内存中彼此“相邻”,但任何保证都会有帮助。

I was wondering if something like this is safe...

// Iterating through a <list>
while ( iter != seq.end()) {
  if ( test ) {
    iter = seq.erase( iter );
  } else {
    ++iter;
 }

I know that iterating through a vector in this way would invalidate the iterator, but would the same thing occur in a list? I assume not since a list is sequential through pointers rather than being "next" to each other in memory, but any reassurance would be helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

一抹苦笑 2024-08-26 13:06:20

这很好,因为擦除方法返回一个新的有效迭代器。

This is just fine because the erase method returns a new valid iterator.

挥剑断情 2024-08-26 13:06:20

是 - std::list::erase():“仅使迭代器和对已擦除元素的引用无效。”

也就是说,您可能根本不应该这样做——您似乎试图模仿std::remove_if()

Yes -- std::list::erase(): "Invalidates only the iterators and references to the erased elements."

That said, you probably shouldn't do this at all -- you seem to be trying to imitate std::remove_if().

梦幻之岛 2024-08-26 13:06:20

该标准定义了每个 STL 容器的擦除行为。对于std::list,只有被擦除元素的迭代器才会失效。不过,erase 的返回值不必是可取消引用的值(也可以是 list.end())。

因此,要删除列表中的所有元素,以下内容绝对有效:

.. it = l.begin();
while(it != l.end()) {
   it = l.erase(it);
}

但要注意类似这样的事情(危险的陷阱):

for (.. it  = l.begin; it != l.end(); ++it) {
      it = l.erase(it);
   }

如果是l.end(),则它会增加两次(第二次增加循环头)。咩。

The standard defines erase behaviour for every STL container. For std::list only iterators to the erased elements are invalidated. The return value of erase needn't be a dereferencable one, though (it could be list.end()).

Therefore, to erase all elements in a list the following is absolutely valid:

.. it = l.begin();
while(it != l.end()) {
   it = l.erase(it);
}

BUT beware of something like this (dangerous pitfall):

for (.. it  = l.begin; it != l.end(); ++it) {
      it = l.erase(it);
   }

If it is l.end(), it is incremented twice (second time by the loop head). Baamm.

吃兔兔 2024-08-26 13:06:20

是的,这是执行此操作的标准方法。请参阅有效 STL,第 9 项(第 46 页)。

Yes, this is the standard way to do that. See Effective STL, Item 9 (p. 46).

橘亓 2024-08-26 13:06:20

是的,这是完全安全的。 erase() 函数返回一个迭代器,指向被擦除元素之后的元素。如果您没有将 erase() 的结果重新分配给 iter,就会遇到麻烦。

Yes, this is totally safe. The erase() function returns an iterator to the element succeeding the one which was erased. Had you not reassigned the result of erase() to iter, you'd have trouble.

原来是傀儡 2024-08-26 13:06:20

正如其他人所解释的,您的代码不会使函数中使用的迭代器无效。但是,如果集合是向量,则它确实会使其他迭代器无效,但如果集合是列表,则不会。

As others have explained, your code does not invalidate the iterator used in the function. However, it does invalidate other iterators if the collection is a vector, but not if the collection is a list.

雨落□心尘 2024-08-26 13:06:20

正如其他人提到的,是的,它会起作用。但我建议使用 list::remove_if 代替,因为它更具表现力。

As others have mentioned, yes, it will work. But I'd recommend using list::remove_if instead, as it's more expressive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文