tags:

views:

406

answers:

6

What I need is just a dynamically growing array. I don't need random access, and I always insert to the end and read it from the beginning to the end.

slist seems to be the first choice, because it provides just enough of what I need. However, I can't tell what benefit I get by using slist instead of vector. Besides, several materials I read about STL say, "vectors are generally the most efficient in time for accessing elements and to add or remove elements from the end of the sequence". Therefore, my question is: for my needs, is slist really a better choice than vector? Thanks in advance.

+3  A: 

Yes, if you are always reading beginning to end, slist (a linked list) sounds like the way to go. The possible exception is if you will be inserting a large quantity of elements at the end at the same time. Then, the vector could be better if you use reserve appropriately.

Of course, profile to be sure it's better for your application.

Matthew Flaschen
That sounds like the opposite of what I've written (and backed up with data) so it's probably not right.
Konrad Rudolph
You didn't provide any data on slist, only the vague promise of it, and a comparison of two other (besides slist) structures.
Matthew Flaschen
Again: sorry. I'm a bit stupid apparently, I confused the benchmarks.
Konrad Rudolph
No problem, Konrad.
Matthew Flaschen
+5  A: 

For starters, slist is non-standard.

For your choice, a linked list will be slower than a vector, count on it. There are two reasons contributing to this:

  1. First and foremost, cache locality; vectors store their elements linearly in the RAM which facilitates caching and pre-fetching.
  2. Secondly, appending to a linked list involves dynamic allocations which add a large overhead. By contrast, vectors most of the time do not need to allocate memory.

However, a std::deque will probably be even faster. In-depth performance analysis has shown that, despite bias to the contrary, std::deque is almost always superior to std::vector in performance (if no random access is needed), due to its improved (chunked) memory allocation strategy.

Konrad Rudolph
What makes you think slist will be slower, and where is this mysterious (and applicable for all applications) performance evaluation? http://www.sgi.com/tech/stl/Deque.html says, "The main way in which deque differs from vector is that deque also supports constant time insertion and removal of elements at the beginning of the sequence." But the OP explicitly said he was never doing insertion or removal at the beginning.
Matthew Flaschen
Also, I find it hard to believe you couldn't find the docs for slist.
Matthew Flaschen
Matthew: Guilty as charged: I was lazy. About your accusation: what the SGI article says is simply outdated; it was believed to be true but benchmarks simply show that `deque` performs better than `vector` even in vector-typical usage. I've linked the relevant analysis.
Konrad Rudolph
Indeed. If we are not handling with very few data items, i would recommend deque too. It's not a coincidence that deque is the default underlying sequence of std::stack. However, for few items, vector should be the default. (std::stack doesn't know how much items will be pushed, so it's going the safe way with deque).
Johannes Schaub - litb
Btw, this is another prime example why calling the standard library "STL" is going to result in much confusion. I never do it, because there are many "STL" meanings, but only one C++ Standard Library meaning.
Johannes Schaub - litb
+1: if there is doubt between using a vector or a (s)list, deque is probably the right choice.
stefaanv
+1  A: 

I'm guessing you mean std::list by "slist". Vectors are good when you need fast, random-access to a sequence of elements, with guaranteed contiguous memory, and fast sequential reading (IOW, from the beginning to the end). Lists are good when you need fast (constant-time) insertion or deletion of items at the beginning or end of the sequence, but don't care about the performance of random-access or sequential reading.

The reason for the difference is the way the 2 are implemented. Vectors are implemented internally as an array of items, which needs to be reallocated when its size/capacity is reached on adding an item. Lists are implemented as a doubly-linked list, which can cause cache-misses for sequential reading. Random-access for lists also requires scanning from the first (or last) item in the list, until it locates the item you're requesting.

Jon Benedicto
Just realize, slist, a singly linked list, is not standard? It does appear in HP/SGI STL though.
gc
Unfortunately, std::list is a doubly-linked list, which is totally unnecessary given the OP's described requirements. Otherwise, I agree with this.
Matthew Flaschen
+2  A: 

Matt Austern (author of "Generic Programming and the STL" and general C++ guru) is a strong advocate of singly-linked lists for inclusion in the forthcoming C++ standard; see his presentation at http://www.accu-usa.org/Slides/SinglyLinkedLists.ppt and his long article at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2543.htm for more details, including a discussion of the trade-offs involved that may guide you in possibly choosing this data structure. (Note that the currently proposed name is forward_list, though slist is how it was traditionally named in SGI's STL & other popular libraries).

Alex Martelli
+1  A: 

I'll second (or maybe third...) the opinion that std::vector or std::deque will do the job. The only thing that I will add is a few additional factors that should guide the decision between std::vector<T> and std::list<T>. These have a lot to do with the characteristics of T and what algorithms you plan on using.

The first is memory overhead. Std::list is a node-based container so if T is a primitive type or relatively small user-defined type, then the memory overhead of the node-based linkage might be non-negligible - consider that std::list<int> is likely to use at least 3 * sizeof(int) storage for each element whereas std::vector will only use sizeof(int) storage with a small header overhead. Std::deque is similar to std::vector but has a small overhead that is linear to N.

The next issue is the cost of copy construction. If T(T const&) is at all expensive, then steer clear of std::vector<T> since it cause a bunch of copies to occur as the size of the vector grows. This is where std::deque<T> is a clear winner and std::list<T> is also a contender.

The final issue that usually guides the decision on container type is whether your algorithms can work with the iterator invalidation constraints of std::vector and std::deque. If you will be manipulating the container elements a lot (e.g., sorting, inserting in the middle, or shuffling), then you might want to lean towards std::list since manipulating the order requires little more than resetting a few linkage pointers.

D.Shawley
A: 

Sounds like a good job for std::deque to me. It has the memory benefits of a vector like contiguous memory allocation for each "slab" (good for CPU caches), no overhead for each element like with std::list and it does not need to reallocate the whole set as std::vector does. Read more about std::deque here

lothar