12

They both have access complexity of O(1) and random insertion/removal complexity of O(n). But vector costs more when expanding because of reallocation and copy, while deque does not have this issue.

It seems deque has a better performance, but why most people use vector instead of deque?

SwiftMango
  • 15,092
  • 13
  • 71
  • 136
  • 2
    `vector` is more efficient when accessing the items. O(1) complexity for both does not mean both use the same number of cycles. Also, reallocating a `vector` will move its items if possible, not necessarily copy them. – syam Sep 26 '13 at 14:51
  • @syam Don't both have access complexity of O(1) ? – SwiftMango Sep 26 '13 at 14:53
  • 6
    @texasbruce: Yes; but `deque` typically has an extra level of indirection, making access slower. O(1) just means it doesn't get worse as the container gets large. Both have amortised O(1) time for adding an element to the end; but your point that vector is (sometimes) slower still stands. – Mike Seymour Sep 26 '13 at 14:54
  • @texasbruce You can have O(1) complexity for a specific operation and it takes 1000 cycles to perform, and O(1) complexity but it takes only 10 cycles. – syam Sep 26 '13 at 14:54
  • 1
    For what is worth, MSVC's deque implementation easily degenerates into effectively a vector of pointers (if `sizeof(T) > 16`) which is just like a vector, but with extra indirections and allocations. – R. Martinho Fernandes Sep 26 '13 at 15:12
  • @texasbruce: `sleep(1)` and `sleep(10000)` both have `O(1)` complexity, but take very different time to complete. – David Rodríguez - dribeas Sep 26 '13 at 15:19
  • **TL;DR** answer as to why a `deque` can sometimes be better/more efficient than a `vector`: 1. It guarantees that elements don't move, so it can act as a more efficient host for items which are permanently pointed to (assuming they're not deleted), even if other elements are inserted or deleted wherever; in other words, it acts as a good sort-of memory bank for keeping semi-permanent external pointers/instances to its data intact. 2. Quick insertion/deletion at the beginning, not just the end, e.g. for a circular/`queue` type of collection. – Andrew Aug 26 '23 at 11:05
  • 3. Large collections, where it will break up that large memory, for both better speed and more efficient RAM usage. For all other cases, it seems `vector` is best: 1. Contiguous memory, so you can do index/pointer arithmetic, efficient large copies, persistent iterators, etc. 2. Faster in all the other cases where `deque`'s aren't more ideal, particularly because there's no extra pointer indirection. **Note** also that they each provide slightly different functionality: `deque` has `push_front()`, `emplace_front()`, and `prepend_range()`, whereas `vector` has `reserve()` and `capacity()`. – Andrew Aug 26 '23 at 11:15

5 Answers5

11
why most people use vector instead of deque?

Because this is what they have been taught.

vector and deque serve slightly different purposes. They can both be used as a simply container of objects, if that's all you need. When learning to program C++, that is all most people need -- a bucket to drop stuff in to, get stuff out of, and walk over.

When StackOverflow is asked a question like "which container should I use by default," the answer is almost invariably vector. The question is generally asked from the context of learning to program in C++, and at the point where a programmer is asking such a question, they don't yet know what they don't know. And there's a lot they don't yet know. So, we (StackOverflow) need a container that fits almost every need for better or worse, can be used in almost any context, and doesn't require that the programmer has asked all the right questions before landing on something approximating the correct answer. Furthermore, the Standard specifically recommends using vector. vector isn't best for all uses, and in fact deque is better than vector for many common uses -- but it's not so much better for a learning programmer that we should vary from the Standard's advice to newbie C++ programmers, so StackOverflow lands on vector.

After having learned the basics of the syntax and, shall we say, the strategies behind programming in C++, programmers split in to two branches: those who care to learn more and write better programs, and those who don't. Those who don't will stick on vector forever. I think many programmers fall in to this camp.

The rarer programmers who try to move beyond this phase start asking other questions -- questions like you've asked here. They know there is lots they don't yet know, and they want to start discovering what those things are. They will quickly (or less quickly) discover that when choosing between vector and deque, some questions they didn't think to ask before are:

  1. Do I need the memory to be contigious?
  2. Do I need to avoid lots of reallocations?
  3. Do I need to keep valid iterators after insertions?
  4. Do I need my collection to be compatible with some ancient C-like function?

Then they really start thinking about the code they are writing, discover yet more stuff they don't know, and the beat goes on...

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • +1 just for the punch-list. (I can think of many "professionals" I've worked with in the past that fail to consider those questions before choosing their containers, sad as that is). The rest is icing. Nice answer. – WhozCraig Sep 26 '13 at 15:19
  • Thanks for the life story and never actually answering the fakking question asked. – Andrew Aug 26 '23 at 10:36
  • @Andrew, I'm perfectly fine with the downvote, but you can keep the passive-aggressive complaining on a 10 year old question. Besides, I did answer the question. Even made it a nice easy-to-use bullet list. – John Dibling Aug 28 '23 at 20:29
  • @JohnDibling Booooooooo. Lengthy paragraphs, and your "easy-to-use bullet list" is just a list of questions. No answers. Not an answer. Bad answer. Get it now? Also it's not passive aggressive. – Andrew Aug 28 '23 at 20:57
  • @Andrew, kthx bye – John Dibling Aug 28 '23 at 21:47
10

But vector costs more when expanding because of reallocation and copy

While it's true that vector sometimes has to reallocate its array as it grows, it will grow exponentially so that the amortised complexity is still O(1). Often, you can avoid reallocations by judicious use of reserve().

It seems deque has a better performance

There are many aspects to performance; the time taken by push_back is just one. In some applications, a container might be modified rarely, or populated on start-up and then never modified. In cases like that, iteration and access speed might be more important.

vector is the simplest possible container: a contiguous array. That means that iteration and random access can be achieved by simple pointer arithmetic, and accessing an element can be as fast as dereferencing a pointer.

deque has further requirements: it must not move the elements. This means that a typical implementation requires an extra level of indirection - it is generally implemented as something like an array of pointers to arrays. This means that element access requires dereferencing two pointers, which will be slower than one.

Of course, often speed is not a critical issue, and you choose containers according to their behavioural properties rather than their performance. You might choose vector if you need the elements to be contiguous, perhaps to work with an API based on pointers and arrays. You might choose deque or list if you want a guarantee that the elements won't move, so you can store pointers to them.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • +1 this and one other are perhaps the best worded answers that directly answer the OP's question and observation. I have a question for you, however. tis true that vectors have an exponential growth pattern, but by the very nature of that fact isn't the amortized insertion complexity geometrically decayed (i.e. the inverse)? Small yes, but 1, I don't understand. – WhozCraig Sep 26 '13 at 15:13
  • @WhozCraig: A reallocation of size `n` will happen at most once every `n` insertions. So the amortised cost is `O(n/n) == O(1)`. – Mike Seymour Sep 26 '13 at 15:15
  • Heh. jeeezo I need to have my morning coffee before doing math. Thanks, Mike. Much apprec. – WhozCraig Sep 26 '13 at 15:16
8

From C++ standard section 23.1.1:

vector is the type of sequence that should be used by default... deque is 
the data structure of choice when most insertions and deletions take place
at the beginning or at the end of the sequence.

However there are some arguments in the opposite direction.

In theory vector is at least as efficient as deque as it provides a subset of its functionality. If your task only needs what vector's interface provides, prefer vector - it can not be worse than a deque.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • 1
    @syam but does not forbid deque to have contiguous storage too. Inefficient but still possible. – Ivaylo Strandjev Sep 26 '13 at 14:56
  • @syam actually, if you leave memory in the front like you do in the back (i.e. put your data in the middle of the memory block) then `push_front` will work just as well as `push_back` – rabensky Sep 26 '13 at 14:59
  • I am removing the part of the paragraph causing further arguments :) – Ivaylo Strandjev Sep 26 '13 at 15:01
  • @cluracan, IvayloStrandjev: removing my now useless comments then. ;) – syam Sep 26 '13 at 15:04
  • @IvayloStrandjev aww... it made for a good discussion. Sad... I'll add it here then: The discussion was about the possibility to implement `std::vector` as a wraparound `std::deque` (with appropriate `deque` implementation of course - so that the storage is continuous) – rabensky Sep 26 '13 at 15:12
  • 2
    It should be noted that Herb Sutter (the author of the linked article) changed his tune to prefer `vector` long ago. http://coding.derkeiler.com/Archive/C_CPP/comp.lang.cpp/2004-10/3161.html – Benjamin Lindley Sep 26 '13 at 15:17
  • Though unlike in the article, Mr.Sutter doesn't give a _good_ reason for that decision neither in that mail, nor in his book. The book does list a couple of reasons such as "vector guarantees blahblah", but in essence they're all more or less of the "oh right, so what" kind of guarantees, or guarantees you don't want. In particular, `vector` guarantees to reallocate in the most _allocator-unfriendly_ possible way, and it guarantees to reserve huge amounts of unused contiguous memory as it grows huge. I'm not saying one shouldn't use `vector`, but I also see no good reason not to use `deque`. – Damon Oct 23 '13 at 15:14
  • This is incorrect (and also contradicts the reason for `deque`'s existence): "it can not be worse than a deque". The other answers have outlined several ways in which it can. – Andrew Aug 26 '23 at 10:49
  • @Andrew which portion of the other answers are you referring to? Although deque supports a superset of the operations available for vector, if you are interested only in the vector specific ones, my argument stands – Ivaylo Strandjev Aug 27 '23 at 11:12
  • @IvayloStrandjev No, it does not. See my 2 comments on the question itself. You're assuming that because in terms of implementation, a vector is a subset of a deque, this means that the vector is superior and more efficient if you only need the vector's functionality; however, that is an incorrect assumption. – Andrew Aug 28 '23 at 13:10
4

For cplusplus :

Therefore they provide a similar functionality as vectors, but with efficient insertion and deletion of elements also at the beginning of the sequence, and not only at its end. But, unlike vectors, deques are not guaranteed to store all its elements in contiguous storage locations, thus not allowing direct access by offsetting pointers to elements.

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • So for a `queue`, buffer, ring, whatever sort of usage, a `deque` definitely makes more sense: you want that quick insertion/deletion at the beginning as well, but you don't want to use a list because you want nearly the speed of a vector rather than constant pointer lookups. This is especially the case for larger collections. But, if you have something smaller, or if you're going for more of a `stack`, where you're only dealing with one end of it, you want to use `vector`. It's a wonder why apparently c++ implements `stack`'s with `deque` by default... – Andrew Aug 26 '23 at 10:46
3

Personally, I prefer using deque (I always end up spoiling myself and having to use push_front for some reason or other), but vector does have its uses/differences, with the main one being:

vector has contiguous memory, while a deque allocates via pages/chunks. Note, the pages/chunks are fairly useful: constant-time insert/erase on the front of the container. It is also typical that a large block of memory broken up into a series of smaller blocks is more efficient than a single block of a memory.

You could also argue that, because deque is 'missing' size reservation methods (capacity/reserve), you have less to worry about.

I highly suggest you read Sutters' GotW on the topic.

Mohammed Hossain
  • 1,319
  • 10
  • 19