std::list
has a remove
method, while the std::vector
doesn't. What is the reason for that?
-
1There are `std::remove` and friends in `
` for `vectors`. – lethal-guitar Oct 31 '13 at 20:56 -
possible duplicate of [why Vector doesn't provide the remove() member function while list provides?](http://stackoverflow.com/questions/6447106/why-vector-doesnt-provide-the-remove-member-function-while-list-provides) – UpAndAdam Oct 31 '13 at 22:09
7 Answers
std::list<>::remove
is a physical removal method, which can be implemented by physically destroying list elements that satisfy certain criteria (by physical destruction I mean the end of element's storage duration). Physical removal is only applicable to lists. It cannot be applied to arrays, like std::vector<>
. It simply is not possible to physically end storage duration of an individual element of an array. Arrays can only be created and destroyed as a whole. This is why std::vector<>
does not have anything similar to std::list<>::remove
.
The universal removal method applicable to all modifiable sequences is what one might call logical removal: the target elements are "removed" from the sequence by overwriting their values with values of elements located further down in the sequence. I.e. the sequence is shifted and compacted by copying the persistent data "to the left". Such logical removal is implemented by freestanding functions, like std::remove
. Such functions are applicable in equal degree to both std::vector<>
and std::list<>
.
In cases where the approach based on immediate physical removal of specific elements applies, it will work more efficiently than the generic approach I referred above as logical removal. That is why it was worth providing it specifically for std::list<>
.

- 312,472
- 42
- 525
- 765
-
This is actually not true. `std::vector` alloocates memory *without calling constructors* (not even empty constructors), and calls the destructors manually when you remove the object rather than using the `delete` function. You can try it yourself by creating a class which prints something on destruction - you'll see how `std::vector::pop_back` calls the destructor. – rabensky Oct 31 '13 at 21:45
-
@cluracan I see nothing wrong in this answer, and certainly nothing that you are contradicting. – Zac Howland Oct 31 '13 at 22:09
-
@cluracan: I don't see the point you are trying to make and how it is relevant. By physical destruction I mean the end of element's storage duration. It is not possible to end storage duration of a single element of an array. That's the whole point here. – AnT stands with Russia Oct 31 '13 at 22:29
-
1@UpAndAdam: There's nothing "horribly wrong" here. Firstly, one more time, it is not possible to physically destroy an element of an array. (What I mean by *physical destruction* is explained above.) Secondly, as for "doing any better", this is just another way of saying what I said above. It just so happens that eliminating elements from a list by their physical destruction is better in many cases. – AnT stands with Russia Oct 31 '13 at 22:32
std::list::remove
removes all items in a list that match the provided value.
std::list<int> myList;
// fill it with numbers
myList.remove(10); // physically removes all instances of 10 from the list
It has a similar function, std::list::remove_if
, which allows you to specify some other predicate.
std::list::remove
(which physically removes the elements) is required to be a member function as it needs to know about the memory structure (that is, it must update the previous and next pointers for each item that needs to be updated, and remove the items), and the entire function is done in linear time (a single iteration of the list can remove all of the requested elements without invalidating any of the iterators pointing to items that remain).
You cannot physically remove a single element from a std::vector
. You either reallocate the entire vector, or you move every element after the removed items and adjust the size
member. The "cleanest" implementation of that set of operations would be to do
// within some instance of vector
void vector::remove(const T& t)
{
erase(std::remove(t), end());
}
Which would require std::vector
to depend on <algorithm>
(something that is currently not required).
As the "sorting" is needed to remove the items without multiple allocations and copies being required. (You do not need to sort a list to physically remove elements).
Contrary to what others are saying, it has nothing to do with speed. It has to do with the algorithm needing to know how the data is stored in memory.
As a side note: This is also a similar reason why std::remove
(and friends) do not actually remove the items from the container they operate on; they just move all the ones that are not going to be removed to the "front" of the container. Without the knowledge of how to actually remove an object from a container, the generic algorithm cannot actually do the removing.

- 15,777
- 1
- 26
- 42
Consider the implementation details of both containers. A vector
has to provide a continuous memory block for storage. In order to remove an element at index n != N
(with N
being the vector's length), all elements from n+1
to N-1
need to be moved. The various functions in the <algorithm>
header implement that behavior, like std::remove
or std::remove_if
. The advantage of these being free-standing functions is that they can work for any type that offers the needed iterators.
A list
on the other hand, is implemented as a linked list structure, so:
- It's fast to remove an element from anywhere
- It's impossible to do it as efficiently using iterators (since the internal structure has to be known and manipulated).

- 4,438
- 1
- 20
- 40
In general in STL the logic is "if it can be done efficiently - then it's a class member. If it's inefficient - then it's an outside function"
This way they make the distinction between "correct" (i.e. "efficient") use of classes vs. "incorrect" (inefficient) use.
For example, random access iterators have a += operator, while other iterators use the std::advance
function.
And in this case - removing elements from an std::list
is very efficient as you don't need to move the remaining values like you do in std::vector

- 2,864
- 13
- 18
-
I do not know who up-voted this answer, but it should not be up-voted. The reason for it being a member function in a `list` is due to the requirement that the algorithm must have too much information about the internal memory of a list in order to manipulate it so it cannot be generic. A `vector` can support a forward-iterator (which a list cannot), that allows it to utilize the generic algorithms requiring forward-iterators. – Zac Howland Oct 31 '13 at 21:25
-
@ZacHowland What prevents a list from having a forward iterator? (note I didn't upvote I'm just curious as a `list` has a forward iterator.) A list has a bidirectional iterator, which in turn is also a forward iterator. – UpAndAdam Oct 31 '13 at 21:44
-
1@ZacHowland what? a list actually *has* a forward iterator! So obviously it *can* have one, as it actually *has* one... – rabensky Oct 31 '13 at 21:47
-
Sorry, I misspoke (mistyped) in my overzealous response. The answer here is still wrong, though. It is *not* because of efficiency; `remove` actually (physically) removes the elements. That is not possible in a `vector` without first sorting the `vector` by what is to be kept and what is to be removed. – Zac Howland Oct 31 '13 at 22:05
-
@UpAndAdam You don't disturb the iterators in a vector until you resize it. Simply swaping items within the vector (which `std::remove` does) will not invalidate any iterators. When you actually do the `erase` operation, you just potentially invalidated every iterator *after* the element you erased. In effect, if you tried to remove an element `T` from a vector the same way `list` does, you would end up resizing the vector `N` times, which would obliterate the iterators; though, theoretically, you could get around this by not using iterators - use indexes, and start at the end of the vector – Zac Howland Oct 31 '13 at 22:24
-
@UpAndAdam so the "sort" operation (which `std::remove` does) simply allows you to not invalidate the iterators to items you plan to keep when you actually call `erase`. – Zac Howland Oct 31 '13 at 22:26
-
@ZacHowland An iterator is invalid if it doesn't point to the same content it was previously, if you sort and move the locations of the values your iterators are invalidated. – UpAndAdam Oct 31 '13 at 22:49
-
1@UpAndAdam No, the iterators are not invalidated after a sort. The objects they point to have a different value. That is all. – juanchopanza Oct 31 '13 at 22:53
-
@juanchopanza You are going by a technical and generally USELESS definition of invalidated. If I have several iterators that I'm using to perform an operation on with a vector, and you sort the vector all of my iterators are useless and no longer pointing to the objects they previously were pointing to. go look at http://stackoverflow.com/questions/3747691/stdvector-iterator-invalidation – UpAndAdam Oct 31 '13 at 23:00
-
@juanchopanza they don't just have a different value, they are potentially a different object. – UpAndAdam Oct 31 '13 at 23:04
-
@UpAndAdam he is going by the *actual* definition of invalidated. As long as the iterator is still pointing to *valid* data in the container, it is a valid iterator. This is what allows algorithms like `std::unique` and `std::remove` to work. – Zac Howland Oct 31 '13 at 23:22
-
@ZacHowland http://stackoverflow.com/questions/6438086/iterator-invalidation-rules begs to differ. And here too: http://c2.com/cgi/wiki?IteratorInvalidationProblem – UpAndAdam Nov 01 '13 at 03:19
-
And since you guys don't believe me, go to SGI's stl documentation for yourself, http://www.sgi.com/tech/stl/Vector.html : [5] A vector's iterators are invalidated when its memory is reallocated. Additionally, inserting or deleting an element in the middle of a vector invalidates all iterators that point to elements following the insertion or deletion point. It follows that you can prevent a vector's iterators from being invalidated if you use reserve() to preallocate as much memory as the vector will ever use, and if all insertions and deletions are at the vector's end. – UpAndAdam Nov 01 '13 at 03:34
-
1@UpAndAdam I was referring to `std::sort` and `std::remove`. Neither of those invalidates iterators. That is according to the definitions in the C++ standard. – juanchopanza Nov 01 '13 at 06:07
-
@UpAndAdam `An iterator is invalid if it doesn't point to the same content it was previously` <-- this is what we were stating is incorrect. You are mixing up the operations of algorithms like `std::sort` with `erase`. `erase` invalidates all iterators after the deletion point because it cannot guarantee it still points to anything. Similarly, if you insert (anywhere) in a vector, all iterators are invalidated (since a reallocation of memory actually moves the array in memory - e.g. the iterator is *pointing* to a block of memory that the vector is no longer using). – Zac Howland Nov 01 '13 at 13:17
It's all about efficiency AND reference/pointer/iterator validity. list
items can be removed without disturbing any other pointers and iterators. This is not true for a vector
and other containers in all but the most trivial cases. Nothing prevents use the external strategy, but you have a superior options.. That said this fellow said it better than I could on a duplicate question
From another poster on a duplicate question:
The question is not why std::vector does not offer the operation, but rather why does std::list offer it. The design of the STL is focused on the separation of the containers and the algorithms by means of iterators, and in all cases where an algorithm can be implemented efficiently in terms of iterators, that is the option.
There are, however, cases where there are specific operations that can be implemented much more efficiently with knowledge of the container. That is the case of removing elements from a container. The cost of using the remove-erase idiom is linear in the size of the container (which cannot be reduced much), but that hides the fact that in the worst case all but one of those operations are copies of the objects (the only element that matches is the first), and those copies can represent quite a big hidden cost.
By implementing the operation as a method in std::list the complexity of the operation will still be linear, but the associated cost for each one of the elements removed is very low, a couple of pointer copies and releasing of a node in memory. At the same time, the implementation as part of the list can offer stronger guarantees: pointers, references and iterators to elements that are not erased do not become invalidated in the operation.
Another example of an algorithm that is implemented in the specific container is std::list::sort, that uses mergesort that is less efficient than std::sort but does not require random-access iterators.
So basically, algorithms are implemented as free functions with iterators unless there is a strong reason to provide a particular implementation in a concrete container.

- 4,515
- 3
- 28
- 46
std::list
is designed to work like a linked list. That is, it is designed (you might say optimized) for constant time insertion and removal ... but access is relatively slow (as it typically requires traversing the list).
std::vector
is designed for constant-time access, like an array. So it is optimized for random access ... but insertion and removal are really only supposed to be done at the "tail" or "end", elsewhere they're typically going to be much slower.
Different data structures with different purposes ... therefore different operations.

- 2,226
- 32
- 39
To remove an element from a container you have to find it first. There's a big difference between sorted and unsorted vectors, so in general, it's not possible to implement an efficient remove method for the vector.

- 661
- 4
- 5
-
1`std::list` is not sorted either. This has nothing to do with why `std::list` has a `remove` method (or a `sort`, `unique`, etc. method) as a class member. – Zac Howland Oct 31 '13 at 21:31
-
Just because operating with pointers is less expensive than with objects. std::remove algorithm is applicable for std::list but it copies data by value while list::remove does that by pointers – dnk Oct 31 '13 at 21:45
-
1