I\'ve been reading up on STL containers in my book on C++, specifically the section on the STL and its containers. Now I do understand each and every one of them have their
Simple answer: use std::vector
for everything unless you have a real reason to do otherwise.
When you find a case where you're thinking, "Gee, std::vector
doesn't work well here because of X", go on the basis of X.
I expanded on Mikael Persson's fantastic flowchart. I added some container categories, the array container, and some notes. If you'd like your own copy, here is the Google Drawing. Thanks, Mikael for doing the groundwork! C++ Container Picker
One lesson I've learned is: Try to wrap it in a class, since changing the container type one fine day can yield big surprises.
class CollectionOfFoo {
Collection<Foo*> foos;
.. delegate methods specifically
}
It doesn't cost much up front, and saves time in debugging when you want to break whenever somebody does operation x on this structure.
Coming to selecting the perfect data structure for a job:
Each data structure provides some operations, which can be varying time complexity:
O(1), O(lg N), O (N), etc.
You essentially have to take a best guess, on which operations will be done most, and use a data structure which has that operation as O(1).
Simple, isn't it (-:
I answered this in another question which is marked as dup of this one. But I feel that it is nice to refer to some good articles regarding the decision to choose a standard container.
As @David Thornley answered, std::vector is the way to go if there are no other special needs. This is the advice given by the creator of C++, Bjarne Stroustrup in a 2014 blog.
Here is the link for the article https://isocpp.org/blog/2014/06/stroustrup-lists
and quote from that one,
And, yes, my recommendation is to use std::vector by default.
In the comments, user @NathanOliver also provides another good blog, which has more concrete measurements. https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html .
It all depends on what you want to store and what you want to do with the container. Here are some (very non-exhaustive) examples for the container classes that I tend to use most:
vector
: Compact layout with little or no memory overhead per contained object. Efficient to iterate over. Append, insert and erase can be expensive, particularly for complex objects. Cheap to find a contained object by index, e.g. myVector[10]. Use where you would have used an array in C. Good where you have a lot of simple objects (e.g. int). Don't forget to use reserve()
before adding a lot of objects to the container.
list
: Small memory overhead per contained object. Efficient to iterate over. Append, insert and erase are cheap. Use where you would have used a linked list in C.
set
(and multiset
): Significant memory overhead per contained object. Use where you need to find out quickly if that container contains a given object, or merge containers efficiently.
map
(and multimap
): Significant memory overhead per contained object. Use where you want to store key-value pairs and look up values by key quickly.
The flow chart on the cheat sheet suggested by zdan provides a more exhaustive guide.
Here is a flowchart inspired by David Moore's version (see above) that I created, which is up-to-date (mostly) with the new standard (C++11). This is only my personal take on it, it's not indisputable, but I figured it could be valuable to this discussion: