121

What is the difference between std::array and std::vector? When do you use one over other?

I have always used and considered std:vector as an C++ way of using C arrays, so what is the difference?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alok Save
  • 202,538
  • 53
  • 430
  • 533

6 Answers6

163

std::array is just a class version of the classic C array. That means its size is fixed at compile time and it will be allocated as a single chunk (e.g. taking space on the stack). The advantage it has is slightly better performance because there is no indirection between the object and the arrayed data.

std::vector is a small class containing pointers into the heap. (So when you allocate a std::vector, it always calls new.) They are slightly slower to access because those pointers have to be chased to get to the arrayed data... But in exchange for that, they can be resized and they only take a trivial amount of stack space no matter how large they are.

[edit]

As for when to use one over the other, honestly std::vector is almost always what you want. Creating large objects on the stack is generally frowned upon, and the extra level of indirection is usually irrelevant. (For example, if you iterate through all of the elements, the extra memory access only happens once at the start of the loop.)

The vector's elements are guaranteed to be contiguous, so you can pass &vec[0] to any function expecting a pointer to an array; e.g., C library routines. (As an aside, std::vector<char> buf(8192); is a great way to allocate a local buffer for calls to read/write or similar without directly invoking new.)

That said, the lack of that extra level of indirection, plus the compile-time constant size, can make std::array significantly faster for a very small array that gets created/destroyed/accessed a lot.

So my advice would be: Use std::vector unless (a) your profiler tells you that you have a problem and (b) the array is tiny.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • 1
    Wait, what overhead? Both have an indirection through a "pointer". The "pointer" in case of the `std::array` is just camouflaged as an `T arr[N];`. – Xeo Jul 09 '11 at 05:37
  • @Xeo : In `array`'s case, the pointee is the same address as the `array` itself, so no indirection occurs. I.e., Nemo's point is wholly valid. – ildjarn Jul 09 '11 at 05:39
  • 12
    @Xeo: That is not a pointer; it is an array. It is actually _inside_ the object; not _pointed to_ by the object. If you look at the generated asssembly code, you will find accessing a vector element involves one more memory access than an array. (Although in practice it is often irrelevant; e.g. looping through a vector only does the extra indirection once at the start of the loop.) – Nemo Jul 09 '11 at 05:39
  • 6
    @Xeo: Not quite: `std::vector`'s data is stored in separately-allocated memory. `std::array`'s data is not. (Where's the -1 button for comments when you need it?) – C. K. Young Jul 09 '11 at 05:40
  • 1
    +1, but I'll point out that "object-oriented" could be misleading... std::array doesn't have to contain objects (nor does std::vector, for that matter). – Caleb Jul 09 '11 at 05:45
  • 1
    @Caleb: That's not true. Both `std::vector` and `std::array` _must_ use object types. You couldn't have (for example) a `std::vector` of references or a `std::array` of functions. – CB Bailey Jul 09 '11 at 08:14
  • @Charles: Although C and C++ use the term "object" technically, I think it's questionable whether the use of C++ objects is necessarily "object-oriented", since that term has its own separate usage outside C and C++, and isn't defined in C or C++. C's `int` is hardly "object-oriented". You get different definitions of OO from different people, though, so it's not certain, but I think it would mislead some people. Say perhaps that `std::array` is "just a class version of a classic C array type"? – Steve Jessop Jul 09 '11 at 09:05
  • @CharlesBailey: Perhaps we mean different things by "object", but `std::vector vec(10);` declares a perfectly good vector of integers. Likewise, `std::array a;` creates a valid array of integers. Contrast this with Objective-C's NSArray class, which cannot store values of type int, but requires instead that they first be wrapped in a container like NSNumber or NSValue. I'll take your word on functions, but you could certainly declare a std::vector or std::array of function pointers. – Caleb Jul 09 '11 at 15:25
  • @Caleb: But I would say `int a[10]` does not declare an object, while `std::array a` does. That is all I meant by "an object-oriented version of the classic C array". I will change it to @Steve's wording. – Nemo Jul 09 '11 at 15:29
  • @Caleb: `vec` is an object, and it contains objects of type `int`; `a` is also an object and also contains objects of type `int`. I don't think you are disagreeing with me. (Or if you are, I don't understand how.) – CB Bailey Jul 09 '11 at 15:42
  • @Nemo: Why is `int[10]` any less of an object type than `std::array` ? Part of the benefit of C++'s object-oriented features is that you can introduce new types and manipulate objects of user-defined types (class types) in many of the same ways that you can manipulate objects of built-in types. – CB Bailey Jul 09 '11 at 15:50
  • @Charles: Yeah, I was not thinking of built-in types as "objects", but that was a mistake. Which is why I changed to the phrasing suggested by @Steve. – Nemo Jul 09 '11 at 15:52
  • 1
    @CharlesBailey, I don't think we're disagreeing either, just using "object" in two different ways. Section 4.9.6 of *The C++ Programming Langauge* talks about objects as "something in memory," which I think is the way you're using the word. I tend to think of "object" as meaning "an instance of a class," and I think that's strongly implied by "object oriented." For example, section 2.6, titled *Object-Oriented Programming*, talks specifically about classes. That's why I consider the phrase "object oriented" to be potentially misleading as it was applied to std::vector in this answer. – Caleb Jul 10 '11 at 18:28
  • I wonder how many percent of the cache is "a small chunk of data" – jokoon Jun 10 '12 at 11:33
22

I'm going to assume that you know that std::array is compile-time fixed in size, while std::vector is variable size. Also, I'll assume you know that std::array doesn't do dynamic allocation. So instead, I'll answer why you would use std::array instead of std::vector.

Have you ever found yourself doing this:

std::vector<SomeType> vecName(10);

And then you never actually increase the size of the std::vector? If so, then std::array is a good alternative.

But really, std::array (coupled with initializer lists) exists to make C-style arrays almost entirely worthless. They don't generally compete with std::vectors; they compete more with C-style arrays.

Think of it as the C++ committee doing their best to kill off almost all legitimate use of C-style arrays.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
14

std::array

  • is an aggregate
  • is fixed-size
  • requires that its elements be default constructible (vs copy (C++03) or move (C++0x) constructible)
  • is linearly swappable (vs constant time)
  • is linearly movable (vs constant time)
  • potentially pays one less indirection than std::vector

A good use case is when doing things 'close-to-the-metal', while keeping the niceties of C++ and keeping all the bad things of raw arrays out of the way.

Luc Danton
  • 34,649
  • 6
  • 70
  • 114
9

Same reasoning when using a C-style static array rather than a std::vector. And for that, I kindly refer you to here.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • I have to say, I think I like my answer better than any of those. But maybe I am just getting sleepy. – Nemo Jul 09 '11 at 05:41
  • @Nemo: I agree on your answer being better, If you would add up a brief summary of when to use one over other, it would be complete. – Alok Save Jul 09 '11 at 05:46
8

std::array has a fixed (compile time) size, while std::vector can grow.

As such, std::array is like using a C array, while std::vector is like dynamically allocating memory.

Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
  • 1
    this is very important for embedded world. in my environment, I don't have heap and dynamic memory allocation is not allowed. We have only stack. So using vector is prohibited. std::array is nice for us. thanks. – Mehmet Fide Nov 09 '13 at 19:52
  • @MehmetFide I'm curious about what kind of environment is that :) – Floella Oct 13 '16 at 22:06
2

I use my own personal hand coded Array<> template class, which has a simpler API compared with std::array or std::vector. For example:

To use a dynamic Array:

Array<>  myDynamicArray; // Note array size is not given at compile time
myDynamicArray.resize(N); // N is a run time value

...

To use a static Array, fixed size at compile time:

Array<100> myFixedArry;

I believe it has a better syntax than std::array, or std::vector. Also extremely efficient.

Enamul Hassan
  • 5,266
  • 23
  • 39
  • 56
Xiang
  • 21
  • 1