vector vs. list in STL

Viewed 347146

I noticed in Effective STL that

vector is the type of sequence that should be used by default.

What's does it mean? It seems that ignore the efficiency vector can do anything.

Could anybody offer me a scenario where vector is not a feasible option but list must be used?

17 Answers

vector:

  • Contiguous memory.
  • Pre-allocates space for future elements, so extra space required beyond what's necessary for the elements themselves.
  • Each element only requires the space for the element type itself (no extra pointers).
  • Can re-allocate memory for the entire vector any time that you add an element.
  • Insertions at the end are constant, amortized time, but insertions elsewhere are a costly O(n).
  • Erasures at the end of the vector are constant time, but for the rest it's O(n).
  • You can randomly access its elements.
  • Iterators are invalidated if you add or remove elements to or from the vector.
  • You can easily get at the underlying array if you need an array of the elements.

list:

  • Non-contiguous memory.
  • No pre-allocated memory. The memory overhead for the list itself is constant.
  • Each element requires extra space for the node which holds the element, including pointers to the next and previous elements in the list.
  • Never has to re-allocate memory for the whole list just because you add an element.
  • Insertions and erasures are cheap no matter where in the list they occur.
  • It's cheap to combine lists with splicing.
  • You cannot randomly access elements, so getting at a particular element in the list can be expensive.
  • Iterators remain valid even when you add or remove elements from the list.
  • If you need an array of the elements, you'll have to create a new one and add them all to it, since there is no underlying array.

In general, use vector when you don't care what type of sequential container that you're using, but if you're doing many insertions or erasures to and from anywhere in the container other than the end, you're going to want to use list. Or if you need random access, then you're going to want vector, not list. Other than that, there are naturally instances where you're going to need one or the other based on your application, but in general, those are good guidelines.

If you don't need to insert elements often then a vector will be more efficient. It has much better CPU cache locality than a list. In other words, accessing one element makes it very likely that the next element is present in the cache and can be retrieved without having to read slow RAM.

Make it simple-
At the end of the day when you are confused choosing containers in C++ use this flow chart image ( Say thanks to me ) :-

enter image description here

Vector-

  1. vector is based on contagious memory
  2. vector is way to go for small data-set
  3. vector perform fastest while traversing on data-set
  4. vector insertion deletion is slow on huge data-set but fast for very small

List-

  1. list is based on heap memory
  2. list is way to go for very huge data-set
  3. list is comparatively slow on traversing small data-set but fast at huge data-set
  4. list insertion deletion is fast on huge data-set but slow on smaller ones

One special capability of std::list is splicing (linking or moving part of or a whole list into a different list).

Or perhaps if your contents are very expensive to copy. In such a case it might be cheaper, for example, to sort the collection with a list.

Also note that if the collection is small (and the contents are not particularly expensive to copy), a vector might still outperform a list, even if you insert and erase anywhere. A list allocates each node individually, and that might be much more costly than moving a few simple objects around.

I don't think there are very hard rules. It depends on what you mostly want to do with the container, as well as on how large you expect the container to be and the contained type. A vector generally trumps a list, because it allocates its contents as a single contiguous block (it is basically a dynamically allocated array, and in most circumstances an array is the most efficient way to hold a bunch of things).

Any time you cannot have iterators invalidated.

Basically a vector is an array with automatic memory management. The data is contiguous in memory. Trying to insert data in the middle is a costly operation.

In a list the data is stored in unrelated memory locations. Inserting in the middle doesn't involve copying some of the data to make room for the new one.

To answer more specifically your question I'll quote this page

vectors are generally the most efficient in time for accessing elements and to add or remove elements from the end of the sequence. For operations that involve inserting or removing elements at positions other than the end, they perform worse than deques and lists, and have less consistent iterators and references than lists.

When you have a lot of insertion or deletion in the middle of the sequence. e.g. a memory manager.

Summarizing the answers in a table for quick reference:

Vector List
Access Faster Slower
Insert/Delete Operations Slower Faster
Memory Allocation Contiguous Non-contiguous
Size Pre-allocation Need to be reserved Not necessary to reserve
Space Required Per Element Only for the element itself For element and pointers to next
(and optionally previous elements)

In the case of a vector and list, the main differences that stick out to me are the following:

vector

  • A vector stores its elements in contiguous memory. Therefore, random access is possible inside a vector which means that accessing an element of a vector is very fast because we can simply multiply the base address with the item index to access that element. In fact, it takes only O(1) or constant time for this purpose.

  • Since a vector basically wraps an array, every time you insert an element into the vector (dynamic array), it has to resize itself by finding a new contiguous block of memory to accommodate the new elements which is time-costly.

  • It does not consume extra memory to store any pointers to other elements within it.

list

  • A list stores its elements in non-contiguous memory. Therefore, random access is not possible inside a list which means that to access its elements we have to use the pointers and traverse the list which is slower relative to vector. This takes O(n) or linear time which is slower than O(1).

  • Since a list uses non-contiguous memory, the time taken to insert an element inside a list is a lot more efficient than in the case of its vector counterpart because reallocation of memory is avoided.

  • It consumes extra memory to store pointers to the element before and after a particular element.

So, keeping these differences in mind, we usually consider memory, frequent random access and insertion to decide the winner of vector vs list in a given scenario.

Preserving the validity of iterators is one reason to use a list. Another is when you don't want a vector to reallocate when pushing items. This can be managed by an intelligent use of reserve(), but in some cases it might be easier or more feasible to just use a list.

When you want to move objects between containers, you can use list::splice.

For example, a graph partitioning algorithm may have a constant number of objects recursively divided among an increasing number of containers. The objects should be initialized once and always remain at the same locations in memory. It's much faster to rearrange them by relinking than by reallocating.

Edit: as libraries prepare to implement C++0x, the general case of splicing a subsequence into a list is becoming linear complexity with the length of the sequence. This is because splice (now) needs to iterate over the sequence to count the number of elements in it. (Because the list needs to record its size.) Simply counting and re-linking the list is still faster than any alternative, and splicing an entire list or a single element are special cases with constant complexity. But, if you have long sequences to splice, you might have to dig around for a better, old-fashioned, non-compliant container.

The only hard rule where list must be used is where you need to distribute pointers to elements of the container.

Unlike with vector, you know that the memory of elements won't be reallocated. If it could be then you might have pointers to unused memory, which is at best a big no-no and at worst a SEGFAULT.

(Technically a vector of *_ptr would also work but in that case you are emulating list so that's just semantics.)

Other soft rules have to do with the possible performance issues of inserting elements into the middle of a container, whereupon list would be preferable.

Lists are just a wrapper for a doubly-LinkedList in stl, thus offering feature you might expect from d-linklist namely O(1) insertion and deletion. While vectors are contagious data sequence which works like a dynamic array.P.S- easier to traverse.

List is Doubly Linked List so it is easy to insert and delete an element. We have to just change the few pointers, whereas in vector if we want to insert an element in the middle then each element after it has to shift by one index. Also if the size of the vector is full then it has to first increase its size. So it is an expensive operation. So wherever insertion and deletion operations are required to be performed more often in such a case list should be used.

Related