Is there any reason to use `remove` outside of the delete-remove idiom?

As for the algorithm, deleting a set of elements from an adjacent array can be effectively performed in two parts.

  • Move all items that will not be deleted to the front of the array.
  • Mark the array less.

This can be done in C++ with the erase-delete idiom.

 vector<T> v; // v = {0,1,2,3,0,0,7}; vector<T>::iterator it = remove(v.begin(),v.end(),e); // move all elements not to be deleted to the front // Yes, remove is not the brightest name for that. // Especially as list::remove really remove elements from the list. // now v = {1,2,3,7,?,?,?} results marked in question marks // are implementation dependent. v.erase(it,v.end()); // get rid of the elements marked as question marks. // v = {1,2,3,7} 

Now the contents of the elements in the question mark are unknown. The only thing we can do with them is to get rid of them (overwriting them or deleting them).

Is there a real situation where you need to use remove without erasing? The only situation I could think of is

 copy(src.begin(),src.end(),remove(v.begin(),v.end(),e),v.end()); 

replacing all A with B s and requiring that all of these new B be adjacent. Doesn't make much sense.

to change . Does it make sense for anything other than a container container ( deque and vector )?

If I'm really right, why was it implemented as a stand-alone algorithm, and not vector::remove_if , dequeue::remove_if , etc.

+7
source share
5 answers

Your question is going wrong. Rather, one might ask: "Why should I repeat this identical algorithm for each container, instead of making it single, free?"

The basic idea of ​​separating containers, iterators and algorithms is that you do not have a complex explosion as you write more algorithms and more containers. If you want to write a new container with adjacent storage, you can use remove on it right out of the box (provided that you send iterators with direct or random access) without duplicating the code.

The only reason certain containers implement their own versions of member algorithms is because they can do it better than the general version (e.g. std::set::find vs. std::find or list::remove ) , or because they can do something that the general version cannot do (for example, std::list::sort vs. std::sort ). But if you can, you should use the free version for maximum community and versatility.

+6
source

First of all: implementing remove_if as member methods would mean re-duplicating the code. I always thought that the error was in list (why does remove exist: MarkB answered this, in C ++ 03 it is more efficient, and in C ++ 11 it is a bit more efficient)

This is the STL project goal: separate data structures and algorithms, so if you have N structures and M algorithms, you do not have N*M implementations of the algorithms, but only N+M , which are definitely more manageable.

It is noteworthy that the remove specification, that the "left out" elements are indefinite, allows the use of new C ++ 11 move operations for effective removal.

Now, I admit that most of the time it is used as part of the delete-erase idiom. No one is stopping you from creating your own:

  template <typename C> void erase(C& container, typename C::const_reference r) { container.erase(std::remove(container.begin(), container.end(), r), container.end()); } 
+4
source

Yes. A simple counter example:

 void bar { // Get vector of T from foo() vector<T> v = foo(); // Print only non-zero elements. vector<T>::iterator it = remove(v.begin(),v.end(), T(0)); // I could call erase here, but why bother? std::copy(v.begin(), it, std::ostream_iterator<T>(std::cout)); } 

If I am going to use only the selected part of the vector and not use other applications for the vector, I do not need to erase vector. All elements will be destroyed in any case when the vector goes beyond.

+1
source

If for some reason you do not want to resize your container, but just delete some elements and then set some other values ​​to replace the deleted space, then you can just use delete.

As I understand it, the value of deleted items after deletion is not specified, so you cannot use their data. They are as if removed, but space is not freed.

0
source

Yes. first of all, remove() is container independent. You can use it on 2 iterators of any container and should not do such things as:

 if(<iterator is vector iterator>) { vector::remove_if(...); } else(<iterator is dequeue iterator>) { dequeue::remove_if(...); } else(<iterator is list iterator>) { list::remove_if(...); } // etc 

Yes, there is a reason not to execute erase() . For a vector, this makes it smaller and, therefore, performs memory redistribution. Which is not always desirable, because it will cause many copy constructors for other elements of the vector.

0
source

All Articles