Search

6.16 — An introduction to std::vector

In the previous lesson, we introduced std::array, which provides the functionality of C++’s built-in fixed arrays in a safer and more usable form.

Analogously, the C++ standard library provides functionality that makes working with dynamic arrays safer and easier. This functionality is named std::vector.

Unlike std::array, which closely follows the basic functionality of fixed arrays, std::vector comes with some additional tricks up its sleeves. These help make std::vector one of the most useful and versatile tools to have in your C++ toolkit.

An introduction to std::vector

Introduced in C++03, std::vector provides dynamic array functionality that handles its own memory management. This means you can create arrays that have their length set at runtime, without having to explicitly allocate and deallocate memory using new and delete. std::vector lives in the <vector> header.

Declaring a std::vector is simple:

Note that in both the uninitialized and initialized case, you do not need to include the array length at compile time. This is because std::vector will dynamically allocate memory for its contents as requested.

Just like std::array, accessing array elements can be done via the [] operator (which does no bounds checking) or the at() function (which does bounds checking):

In either case, if you request an element that is off the end of the array, the vector will not automatically resize.

As of C++11, you can also assign values to a std::vector using an initializer-list:

In this case, the vector will self-resize to match number of elements provided.

Self-cleanup prevents memory leaks

When a vector variable goes out of scope, it automatically deallocates the memory it controls (if necessary). This is not only handy (as you don’t have to do it yourself), it also helps prevent memory leaks. Consider the following snippet:

If earlyExit is set to true, array will never be deallocated, and the memory will be leaked.

However, if array is a vector, this won’t happen, because the memory will be deallocated as soon as array goes out of scope (regardless of whether the function exits early or not). This makes std::vector much safer to use than doing your own memory allocation.

Vectors remember their length

Unlike built-in dynamic arrays, which don’t know the length of the array they are pointing to, std::vector keeps track of its length. We can ask for the vector’s length via the size() function:

The above example prints:

The length is: 5

Resizing an array

Resizing a built-in dynamically allocated array is complicated. Resizing a std::vector is as simple as calling the resize() function:

This prints:

The length is: 5
0 1 2 0 0

There are two things to note here. First, when we resized the array, the existing element values were preserved! Second, new elements are initialized to the default value for the type (which is 0 for integers).

Vectors may be resized to be smaller:

This prints:

The length is: 3
0 1 2

Resizing a vector is computationally expensive, so you should strive to minimize the number of times you do so.

Compacting bools

std::vector has another cool trick up its sleeves. There is a special implementation for std::vector of type bool that will compact 8 booleans into a byte! This happens behind the scenes, and is largely transparent to you as a programmer.

This prints:

The length is: 5
1 0 0 1 1

More to come

Note that this is an introduction article intended to introduce the basics of std::vector. In a lesson 7.10, we’ll cover some additional capabilities of std::vector, including the difference between a vector’s length and capacity, and take a deeper look into how std::vector handles memory allocation.

Conclusion

Because variables of type std::vector handle their own memory management (which helps prevent memory leaks), remember their length, and can be easily resized, we recommend using std::vector in most cases where dynamic arrays are needed.

6.x -- Chapter 6 comprehensive quiz
Index
6.15 -- An introduction to std::array

130 comments to 6.16 — An introduction to std::vector

  • Taksh

    Hi ALex,

    I was writing some code and tried to use a pointer to a 2 dimensionsal array, but it didn’t work.
    How can I use it?

    Thanks in advance.

    • Alex

      See chapter 6.14, pointers to pointers. There’s code there addressing 2d/multidimensional arrays (for 2d arrays, you need pointers to pointers).

  • justAnotherConfusedStudent

    Is there any reason #include <vector> is before #include <iostream> instead of after it, like we did with #include <string>?

    • Alex

      No. The order of includes should not matter (except if you’re using visual studio precompiled headers, in which case the #include “stdafx.h” needs to be first).

      If you ever find a situation where the order of includes does matter, that means one of the headers you are including isn’t properly including all of the header it needs to operate.

  • Mr C++

    You said, "Resizing dynamically allocated arrays is complicated. ".
    But, How to do so ?
    You Will Tell That Later Or Is it something else?

    • Alex

      I do cover that later, I think when we discuss container classes. You only need to know how to do it if you’re creating your own containers, which you generally shouldn’t do unless no other options are available.

  • Help

    can you say what is wrong with this code(it must print the maximum product of adjacent elements but it does not)
    I did not wrote the main function yet, because the problem is in this function

  • thang

    Hey Alex why when i use sizoef(array) it didn’t print as expect;

    #include <iostream>
    #include <vector>

    int main()
    {
        std::vector<int> array{ 1,2,3,4,5 };
        std::cout << array.size() << "\n" << sizeof(array) << "\n";
    }

    this above code prints 5 and 16 ???

    • Alex

      sizeof() only counts the size of statically allocated memory. It doesn’t not account for dynamically allocated memory. Your std::vector uses 16 bytes of memory (whether it is empty or not). The elements themselves are allocated in dynamically allocated memory, and thus, not counted for the size.

      This is because sizeof() is resolved at compile time, and the compiler can only keep track of statically allocated memory.

  • Deepanshu

    Hi Alex,
    If we want to dynamically allocate a collection of elements, then I want to know which way is faster? Dynamically allocating them by using the ‘new’ operator on the array or by using a std::vector? Please help.

  • gyuren

    My bad SENSEI,,,,,
    meant to say Visual Studio 2013 ULTIMATE v4.5 and not VISUAL BASIC 2013 ULTIMATE.
    I also tried running the std::vector implementation in the code blocks but that too fail.
    But will get a fresh copy of the code blocks and follow the procedures in lesson 0.5 and will give you the feedback.
    I am always humbled by your infinite wisdom and plenty thank you

  • gyuren

    Hello to everyone,
    and Sir Alex you are doing a magnificent job.

    I have read through all the comments and have tried all solutions suggested here to resolve c++11
    compatibility but all fail me.In addition,I have tried running the c++11 vector implementation in
    VISUAL BASIC 2013 ULTIMATE v4.5,GCC and Clang compilers all have failed.I would’ve tried VISUAL
    BASIC 2015 but the file size is not bandwidth friendly
    Now the question:
    Can someone please give me compiler/IDE settings or version which will allow the implementation of the c++11/14
    features.I am a windows guy and a C++ newbie by the way and thank you

    • Alex

      You need Visual C++, not Visual Basic. Visual Basic is a different language. If you look back at lessons 0.5 and 0.6, they show how to install some compilers and configure them for C++11. If bandwidth is a concern, I recommend Code::Blocks.

  • Roy

    Hi Alex,

    I have a question about std::vector and where it is stored in memory. From what I understand from the comments, if you declare a vector without the new keyword it will be stored in the stack and if the new keyword is used it will be stored in the heap, correct? For example:

    Will cause vector1 to be stored in the stack and vector2 to be stored in the heap, correct? Therefore vector1 will be (more) limited in size because of the size constaints on the stack, but have the advantage of self-cleanup, while vector2 will not have the same size limitations, but will have the disadvantage that it does not self-cleanup.

    I also feel that it might be a good idea to add this info to the tutorial, since it is important to be aware of when working with large vectors.

    • Alex

      Kind of. The vector1 object will be allocated on the stack, and the vector2 object will be allocated on the heap. However, std::vector does its own dynamic memory management, so the memory used by the vector will ALWAYS be allocated on the heap, regardless of whether the vector object itself is allocated.

      So the reality is this:
      The vector1 object is on the stack, but the memory it uses is on the heap
      The vector2 pointer is on the stack, the std::vector it points to is on the heap, and the memory it uses is on the heap

      • Jukka

        Hi,

        I think this needs a bit of correction:
        The vector1 object is on the stack, but the memory it uses is on the heap
        The vector2 object is on the *heap, and* the memory it uses is on the heap

        To allocate memory on the stack, an array needs to be used instead. One could use std::array to get stack-allocated memory in C++11 (but this requires knowing the size in advance, just like with C arrays).

  • Dave

    Hi, Alex.

    Nice tutorials!

    I use std::vector to create dynamic one- and two-dimensional arrays.
    One aspect I am presently curious about is initializing all their values to 0.

    If I prompt a user to input an integer value for the size of the arrays, then dynamically create those arrays, will those arrays be zero initialized to default? For example, if I am using arrays of type double, will the entries of those arrays be 0.0 by default (without me looping through them and assigning all their entries 0.0)?

    • Alex

      std::vector won’t zero-initialize the members in its default form, but it has an alternate form that will:

      [code]
      std::vector *v1 = new std::vector(5); // no zero-initialization
      std::vector
      *v2 = new std::vector(5, 6.7); // initialize all members to 6.7
      [code]

      You can use 0.0 instead of 6.7 if you want to initialize to 0.0.

      • Dave

        Thanks for the info, Alex.

        Is there also a way to initialize in a resize operation?

        So, instead of resizing the array at declaration, can it be resized AND initialized later?

        For example,

        I tried to compile this code but the compiler didn’t like it.

        • Alex

          I’m not aware of any way to do a std::vector resize and assignment in one step. Generally you’ll do the resize first, then assign values to individual elements, or the entire vector.

  • John J

    So, originally I just wanted to see what would happen with the first example in C++11 at the top of the page (right before “self clean-up prevents memory leaks”) and I recognized i needed to print out the arrays to see what they would do.  In order to do that I needed a length variable for my for loop.  I kept getting 12/4 and only 3 digits (0,1,2), so then…I just took the second part out completely, and now I’m STILL getting 12/4 and 3 digits printing?!?  Shouldn’t I be getting 20/4 and 5 digits (0,1,2,3,4,5)?  What’s going on, and what did I miss here?

    • Alex

      You’re getting the wrong result for a few reasons.

      First, think of a std::vector like a struct, like this:

      If you take the sizeof() this struct, it will only give you the sizeof the int plus the sizeof the std::string pointer. It will not give you the size of the dynamically allocated array, which is what you actually want!

      You really only should be using sizeof() for fundamental data types, which std::vector is not. If you want to know how many elements are in your std::vector, you can actually just ask it by using the .size() member function, like this:

      Remember, in this context, size() actually means length, not number of bytes.

  • R2New

    Mate, this is brilliant! I am really happy I came across your lessons. cplusplus(dot)com for example is terrible to read and understand. I gonna donate as soon as I land a job.

  • Juan

    Hello,
    I am feeling a little bit stupid, but I am not able to declare and initialize a vector. This is my code:

    #include
    using namespace std;

    int main()
    {
    array2 = { 9, 7, 5, 3, 1 };
    return 0;
    }

    But when I try to compile it I get the error:

    main.cpp: In function ‘int main()’:
    main.cpp:14:45: error: in C++98 ‘array2’ must be initialized by constructor, not by ‘{…}’
    std::vector array2 = { 9, 7, 5, 3, 1 };
    ^
    main.cpp:14:45: error: could not convert ‘{9, 7, 5, 3, 1}’ from ‘’ to ‘std::vector’
    make: *** [main.o] Error 1

    I guess one option would be to switch to C++11, but isn’t there a way in which I can create a vector without adding the elements one by one in C++98?

    Thanks

  • Ninja

    I get an error that says debug assertion failed! vector subscript out of range. I thought you can set the length to whatever you want…

    • Alex

      With a std::vector, using operator[] or the at() function will not change the length of the vector. To change the length of a vector, you need to call resize() (or another function that explicitly changes the vector’s length). I thought I’d mentioned this, but apparently not. I’ll add it to the lesson.

      • Ninja

        I usually write all the code on visual studio as I read the lesson so I got confused when I got an error from the very start. I now understand after I got to the end of the lesson.

  • chump

    Hi Alex, I was messing around and found that this seems to be legal.

      

    I was under the impression that std::vector, by default, is dynamically allocated (heap). I also noticed that the above line is not deallocated automatically when going out of scope.

    Could you clarify whats going on here?

    Btw, great explanations on the tutorials. Thanks a lot for this.

    • Alex

      You’re dynamically allocating a std::vector on the heap. Because you’re the one doing the dynamic allocation, C++ expects you to do the cleanup (deletion).

      If you’d defined this as a local variable:

      it would be cleaned up automatically when v goes out of scope.

      Now, std::vector does do its own internal memory allocation to resize itself to hold the elements. This happens on the heap as well. But that’s irrelevant in this example.

      • chump

        Interesting. So

        is functionally identical to

        with the only difference here being that the std::vector in the 2nd code snippet cleans itself up when going out of scope?
        The 2nd code snippet one is also in the heap (like the one in the 1st code snippet), right?

        • chump

          Seems like I misunderstood what v is in

          &v is located on the stack and effectively "points" to the dynamic memory (I’m assuming this because &v and &(v[0]) are completely different memory addresses) that holds the vector values (it seems to do the dereferencing implicitly).

          So by declaring

          I’m moving this "v" equivalent value to the heap.

          the pointer above from the second snippet is stored in the stack and points to this "v" equivalent value. I came to this conclusion after printing out value for:

          &pointer             //009FF928
          &(*pointer)         //00C58BC0
          &((*pointer)[0])   //00C5F100

          Or am I completely off again?

        • Alex

          In the first example, vector v is dynamically allocated on the heap, so you have to clean it up.
          In the second example, vector v is allocated on the stack, so it will clean itself up when it goes out of scope. So they are not the same.
          In both cases, when the vector dynamically allocates memory internally to hold your integers, that happens on the heap. The vector will clean this up when it is destroyed so you don’t have to worry about it.

          I talk more about the heap and the stack in the next chapter.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter