开发者

Removal of elements during iteration through a list - safety

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.


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


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().


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.


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


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.


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜