6.15 — An introduction to std::array

In previous lessons, we’ve talked at length about fixed and dynamic arrays. Although both are built right into the C++ language, they both have downsides: Fixed arrays decay into pointers, losing the array length information when they do, and dynamic arrays have messy deallocation issues and are challenging to resize without error.

To address these issues, the C++ standard library includes functionality that makes array management easier, std::array and std::vector. We’ll examine std::array in this lesson, and std::vector in the next.

An introduction to std::array

Introduced in C++11, std::array provides fixed array functionality that won’t decay when passed into a function. std::array is defined in the <array> header, inside the std namespace.

Declaring a std::array variable is easy:

Just like the native implementation of fixed arrays, the length of a std::array must be known at compile time.

std::array can be initialized using initializer lists or uniform initialization:

Unlike built-in fixed arrays, with std::array you can not omit the array length when providing an initializer:

However, since C++17, it is allowed to omit the type and size. They can only be omitted together, but not one or the other, and only if the array is explicitly initialized.

We favor this syntax rather than typing out the type and size at the declaration. If your compiler is not C++17 capable, you need to use the explicit syntax instead.

You can also assign values to the array using an initializer list

Accessing std::array values using the subscript operator works just like you would expect:

Just like built-in fixed arrays, the subscript operator does not do any bounds-checking. If an invalid index is provided, bad things will probably happen.

std::array supports a second form of array element access (the at() function) that does bounds checking:

In the above example, the call to checks to ensure array element 1 is valid, and because it is, it returns a reference to array element 1. We then assign the value of 6 to this. However, the call to fails because array element 9 is out of bounds for the array. Instead of returning a reference, the at() function throws an error that terminates the program (note: It’s actually throwing an exception of type std::out_of_range -- we cover exceptions in chapter 15). Because it does bounds checking, at() is slower (but safer) than operator[].

std::array will clean up after itself when it goes out of scope, so there’s no need to do any kind of manual cleanup.

Size and sorting

The size() function can be used to retrieve the length of the std::array:

This prints:

length: 5

Because std::array doesn’t decay to a pointer when passed to a function, the size() function will work even if you call it from within a function:

This also prints:

length: 5

Note that the standard library uses the term “size” to mean the array length — do not get this confused with the results of sizeof() on a native fixed array, which returns the actual size of the array in memory (the size of an element multiplied by the array length). Yes, this nomenclature is inconsistent.

Also note that we passed std::array by (const) reference. This is to prevent the compiler from making a copy of the std::array when the std::array was passed to the function (for performance reasons).


Always pass std::array by reference or const reference

Because the length is always known, range-based for-loops work with std::array:

You can sort std::array using std::sort, which lives in the <algorithm> header:

This prints:

1 3 5 7 9

The sorting function uses iterators, which is a concept we haven’t covered yet, so for now you can treat the parameters to std::sort() as a bit of magic. We’ll explain them later.

Manually indexing std::array via size_type

Pop quiz: What’s wrong with the following code?

The answer is that there’s a likely signed/unsigned mismatch in this code! Due to a curious decision, the size() function and array index parameter to operator[] use a type called size_type, which is defined by the C++ standard as an unsigned integral type. Our loop counter/index (variable i) is a signed int. Therefore both the comparison i < myArray.size() and the array index myArray[i] have type mismatches.

Interestingly enough, size_type isn't a global type (like int or std::size_t). Rather, it's defined inside the definition of std::array (C++ allows nested types). This means when we want to use size_type, we have to prefix it with the full array type (think of std::array acting as a namespace in this regard). In our above example, the fully-prefixed type of "size_type" is std::array<int, 5>::size_type!

Therefore, the correct way to write the above code is as follows:

That's not very readable. Fortunately, std::array::size_type is just an alias for std::size_t, so we can use that instead.

A better solution is to avoid manual indexing of std::array in the first place. Instead, use range-based for-loops (or iterators) if possible.

Keep in mind that unsigned integers wrap around when you reach their limits. A common mistake is to decrement an index that is 0 already, causing a wrap-around to the maximum value. You saw this in the lesson about for-loops, but let's repeat.

This is an infinite loop, producing undefined behavior once i wraps around. There are two issues here. If `myArray` is empty, ie. size() returns 0 (which is possible with std::array), myArray.size() - 1 wraps around. The other issue occurs no matter how many elements there are. i >= 0 is always true, because unsigned integers cannot be less than 0.

A working reverse for-loop for unsigned integers takes an odd shape:

Suddenly we decrement the index in the condition, and we use the postfix -- operator. The condition runs before every iteration, including the first. In the first iteration, i is myArray.size() - 1, because i was decremented in the condition. When i is 0 and about to wrap around, the condition is no longer true and the loop stops. i actually wraps around when we do i-- for the last time, but it's not used afterwards.

Array of struct

Of course std::array isn't limited to numbers as elements. Every type that can be used in a regular array can be used in a std::array.


House number 13 has 120 rooms
House number 14 has 30 rooms
House number 15 has 120 rooms

However, things get a little weird when we try to initialize the array.

Although we can initialize std::array like this if its elements are simple types, like int or std::string, it doesn't work with types that need multiple values to be created. Let's have a look at why this is the case.

std::array is an aggregate type, just like House. There is no special function for the creation of a std::array. Rather, its internal array gets initialized as if it were a member of a struct. To make this easier to understand, we'll implement a simple array type ourselves.

As of now, we can't do this without having to access the value member. You'll learn how to get around that later. This doesn't affect the issue we're observing.

As expected, this works. So does std::array if we use it with int elements. When we instantiate a struct, we can initialize all of its members. If we try to create an Array of Houses, we get an error.

When we use braces inside of the initialization, the compiler will try to initialize one member of the struct for each pair of braces. Rather than initializing the Array like this:

The compiler tries to initialize the Array like this:

The first pair of inner braces initializes value, because value is the first member of Array. Without the other two pairs of braces, there would be one house with number 13, 4 stories, and 30 rooms per story.

A reminder

Braces can be omitted during aggregate initialization:

To initialize all houses, we need to do so in the first pair of braces.

This works, but it's very confusing. So confusing that your compiler might even warn you about it. If we add braces around each element of the array, the initialization is a lot easy to read.

This is why you'll see an extra pair of braces in initializations of std::array.


std::array is a great replacement for built-in fixed arrays. It's efficient, in that it doesn’t use any more memory than built-in fixed arrays. The only real downside of a std::array over a built-in fixed array is a slightly more awkward syntax, that you have to explicitly specify the array length (the compiler won’t calculate it for you from the initializer, unless you also omit the type, which isn't always possible), and the signed/unsigned issues with size and indexing. But those are comparatively minor quibbles — we recommend using std::array over built-in fixed arrays for any non-trivial array use.

6.16 -- An introduction to std::vector
6.14 -- Pointers to pointers and dynamic multidimensional arrays

224 comments to 6.15 — An introduction to std::array

  • Omri

    Hello Alex,
    In the beginning paragraph it is written:
    ...std::array lives in the array header.

    Is it not more correct to say:
    std::array is declared in the array header and defined in std namespace?

  • Le

    Hi Alex,
    I use Microsoft Visual C++ 2008, I include array #include <array> then I compile and I get the error:  "fatal error C1083: Cannot open include file: 'array': No such file or directory". How can I fix it?

    • Alex

      Upgrade your compiler to one that is C++11 compatible. std::array was introduced in C++11, and Visual C++ 2008 is too old to support it.

  • Rohit

    Hi Alex!
    Can I pass a fixed array into a function as a std::array without decaying it to a pointer?See the code below. Is it valid?
    #include <iostream>
    #include <array>

    void printLength(const std::array<double, 5> &myarray)
        std::cout << "length: " << myarray.size();

    int main()
        myarray = { 9.0, 7.2, 5.4, 3.6, 1.8 };


        return 0;

    • Alex

      Yes, std::array doesn't decay like a fixed array would. But in your sample code, your declaration of myarray doesn't have a type. It should be std::array.

      • Rohit

        Thsts by mistake, I forgot to write the type of myarray.
        suppose i write int myarray = { 9.0, 7.2, 5.4, 3.6, 1.8 };
        and pass this fixed array as a std::array, now will the array decay or not?
        Is is possible to define a fixed array and pass it as an std::array?

        • Alex

          You can't define a fixed array and pass it as a std::array. You either have to pass the fixed array by reference, or create it as a std::array in the first place and then pass the std:array (also by reference).

  • Mike

    for this example:

    surely having to specify the length of the std::array in the function declaration defeats the purpose of returning its size?

    • Alex

      We don't return its size, we just print its size to the console.

      That said, you may be wondering why I didn't do this:

      First, just to illustrate how the size() function works. Second, this code will work even if the array size is later changed (or templated). It's less error prone, since changing the array size only needs to be done in the function parameter, not in the function code as well.

  • Evgeny

    Hi Alex!

    This is the first chapter where I feel I need to raise a question (really comprehensive tutorial, thank you).

    When defining a function
        void printLength(const std::array<double, 5> &myarray)
    is it possible to generalize it for an arbitrary array size, not only 5?

    • Alex

      Yes, you can do this via partial template specialization:

      I talk about this more in chapter 13, in the lesson on partial template specialization.

  • Mario

    I have always seen your rules as something that is true independant of the context, but im not sure about this:

      'Rule: Always pass std::array by (const) reference'

    Is this not true if a function is supposed to change the content of the array?

    Or is it still possible to change the value(s) of the array passed to the function even if it is const?
    Maybe because std::array works with pointers and const does not let you change the address of the pointer but the variable the pointer is pointing to?

    Please tell me if I am missing something.

    By the way, these tutorials are great. Keep up the good work!

    Regards Mario

  • Chen

    Hi Alex, thanks for the great tutorial!

    Using global symbolic constant (which you introduced in Lesson 4.2) with the str:array can cause a compiling error.

    error : the value of ‘Constants::GSC’ is not usable in a constant expression

    I know it's kind of an overkill, but to be of self-consistency, do you have any suggestion for a workaround? Thanks!




    • Alex

      It doesn't work for fixed array sizes either. Took me a bit of digging to figure out why -- because the definition of the size (variable GSC) is in a different compilation unit than the array, the compiler can't determine the array size at compilation time. This value is effectively treated as a runtime constant, rather than a compile-time constant.

  • Austin

    The array header actually includes the algorithm header, so you don't need to include it separately.

  • Lam Gia Khang

    I am having confusion about the size of array in std::array

    Why the final result here is 5? So the myarray.size() here is different from sizeof(myarray)? And the last question is: when we talk about the size of the array, it means the number of elements or the total size (number of elements*size of type)?

    • Alex

      The final result is 5 because size() returns the length of the array, which is 5. size() is different than sizeof() -- in this case, the sizeof(myarray) is 40 (5 elements * 8 bytes per double).

      When we talk about the size of something, we more often mean the sizeof the object (but not always). That's why I try to use the word length when referring to the length of the array.

      In my opinion, the C++ designers made a mistake by naming the function size() instead of length().

  • RWDavid

    Hi Alex,
    I was wondering, since you can't omit the array size of an std::array, doesn't it add a bit more difficulty for re-using functions with array parameters?

    You can pass in any array of type int into the doSomething function, but how can you make parameters such that an std::array of type int can be passed in, regardless of its length?

    • Alex

      You can't directly. There's a workaround by using a template parameter for the array size, but that's an advanced topic that we don't cover until much later.

      If you want to do this, you may be better off using a std::vector, which doesn't require you to define the size at compile time.

  • DeNiSkA

    I am having confusion about using 'const references' when passing an array.
    The reason you gave was to protect compiler from making copy of it, but what will happen if compiler makes the copy?

    • Alex

      Just uses extra time and memory. Most of the time this just bloats the memory usage and running speed of your application, but occasionally if the array is large enough it could cause your program to crash (if you run out of stack memory).

      • DeNiSkA

        I understand use of reference but why we use 'const'?

        • Alex

          Const references allow us to do three things:
          1) Pass const arguments (you can't pass a const argument to a non-const parameter)
          2) Pass literals (you can't pass a literal to a non-const reference)
          3) Ensure the function doesn't change the value of the argument

  • Vlad

    Hello Alex

    When using the previous fixed arrays, it's possible to print out the address of the (1st element of the) array by using:

    However, for std::array, it doesn't work anymore, you need to explicitly use the address-of operator:

    Is this because of it not decaying into a pointer? I then used:

    and this is what came out (codeblocks archlinux x64):

    I expect a green face anytime. I can see "array", I guess 3EE is the length (size -- deduced through changes), the rest are very confusing. What are those and what type is an array created with std::array?

    • Alex

      Yes, you need the & with the std::array because it's not decaying into a pointer.

      I can't tell you what all those symbols printed by mean. Each compiler is free to choose its own representations, so there's no consistency.

  • Elpidius

    It is a bit more difficult to declare multi-dimensional arrays using std::array relative to arrays built into the C++ language, however I've provided examples below for those curious to know how to do so.

    Examples of two-dimensional std::array variables:

    This prints:

    An example of a three-dimensional std::array variable:

    This prints:

  • shreyanshd

    Hi Alex. Which algorithm does the

    method implement internally? Also, do we have an option to change(choose) the algorithm used to sort the array?

    • Alex

      It's up to the compiler implementer to pick a sorting routine. Most compilers use quicksort or a variation of quicksort. I'm not aware of a way to explicitly pick a sorting method.

  • Nyap

    on the second example in size and sorting you need to #include <array>

  • Waris

    Hi Alex,

    I added the following header file under the existing 3 lines, then problem was fixed.

    But I could not explain why this can solve the problem. I am using the same Microsoft Visual C++ 2015. Thanks!

    • Alex

      Aah, yes. You used std::string but you did not include the string header. If you use std::string in a file, you need to include the string header, otherwise C++ won't know what a string is.

  • Waris

    Hello Alex,
    I am beginner for C++. Thank you for this great tutorial. I changed the example code in this lesson to sort strings as follows:

    #include <iostream>
    #include <array>
    #include <algorithm> // for std::sort

    int main()
        std::array<std::string, 5> myarray{ "Blue", "Green", "White", "Yellow", "Black" };
        //std::sort(myarray.begin(), myarray.end()); // sort the array forwards
        std::sort(myarray.rbegin(), myarray.rend()); // sort the array backwards

        for (const auto &element : myarray)
            std::cout << element << ' ';

        std::cout << std::endl;
        return 0;

    However, during compile there is an error
    "no operator "<<" matches these operands    Std_Array"

    for line 16       std::cout << element << ' ';

    When I change "element" to "element[1]", set a breakpoint at this line and run the code, I can see "element" refers to a string. It is one of the colors I input. Can you help me with my mistake?

    Thanks Again.

    • Alex

      Not sure, I pasted your code into Visual Studio 2015 and it compiled and ran fine. What compiler are you using? Is it C++11 compatible?

  • Jim

    On the initializer lists shown below you make comments that the first two are okay but the last one is not since it has to many elements.  You also comment that the seconds one has elements 3 and 4 are set to zero.
    This is confusing unless you referring to some other code. Or you just want five elements in all the lists.
    How do you know this from this code as its shown? How many elements are you allowed to put in the lnitializer list ?

    myarray = { 0, 1, 2, 3, 4 }; // okay
    myarray = { 9, 8, 7 }; // okay, elements 3 and 4 are set to zero!
    myarray = { 0, 1, 2, 3, 4, 5 }; // not allowed, too many elements in initializer list!

    • Alex

      In the example, I was working under the assumption we were using the same myarray variable declared above, which had a length of 5. I've updated the lesson to make this more explicit.

      You can have as many elements as you want in an initializer list. However, the compiler will complain if the initializer list contains more elements than the std::array you are trying to assign it to.

  • Chris

    why line 8 error?

    • Alex

      The subscript already does an implicit dereference, so by using both * and [], you're trying to do one too many dereferences.

      That said, std::array also won't let you deference it using * (only []).

      • Chris

        i try delete the * but it still error..

        • Alex

          Sorry, I misled you. The proper way to do what you want is as follows:

          (*arrayPtr)[0] = 5;

          If you were using a standard fixed array, what I said would have been true. But std::array (and other classes) work a bit differently, since they won't decay into a pointer.

  • Connor

    Hi Alex. First off, thanks for answering questions posted - they've really helped me develop. Another one for you though:

    if a function has a std::array passed to it, i.e.

    why can't I pass a standard array such as:

    does an array defined as

    not convert to


  • Aaron

    Is there an error in the example of how to pass an array to a function? It says:

    Shouldn't it be:

  • DanL

    Also wanted to chime in that the use of "array" as a variable name is really confusing.  How about "sampleArray" or something?

  • Aymen

    Loving the information and tutorials Alex, thanks alot

    PS: I'm not sure if this is a typo its just I'v never hear of build-in component; in the summary you've stated: " build-in fixed arrays." - Thanks Again :)

  • Rob G.

    Removed the ampersand, still works. Suspect we are copying now instead of changing data at source address (&).

    • Alex

      Correct, the argument would now be passed by value, making a copy of my_array. It'll still work, but it's slower because making a copy of a std::array isn't fast.

  • Rob G.

    Hi Alex I am learning so much from your efforts! Only thing - the tutorial didn't give an example of passing a container into the function (std::array) though it was mentioned. So I took the onus on myself to prove : ) that the std::array doesn't decay when passed! My question:(std::array<int,6>&my_array). What does the &my_array do? Pass by reference to the original storage location of my_array?

    • Alex

      Passing std::array into a function works just like passing a normal non-pointer variable, outside of the fact that you should pass it by reference instead of by value.

      In the context of a function parameter, the ampersand (&) means pass by reference. So in your case, the my_array parameter in fx_print_element_num() is a reference to the argument passed in (the my_array variable in main).

  • Nortski

    Hi Alex,

    When passing an std::array to a function, does it copy all the elements thus being a downside over fixed arrays as more memory will be used?

    Many thanks!

    • Alex

      Depends on how you pass it. If you pass it by value, then yes, it will copy all of the elements. If you pass it by address or reference, then no. Generally you'll want to pass it by reference to avoid the copying.

  • Summary

    std::array is a great replacement for build-in fixed arrays. It’s efficient, in that it doesn’t use any more memory than built-in fixed arrays..


    How std::array don't use more memory?

    • Alex

      Why would you expect it to?

      • Shiva

        May be because it is a user-defined class? I don't know, but it must have it's member functions and such right? From school I know that the class methods are allocated a single space, while objects are allocated memory for separate member variables. The sizeof operator returns 20 for both the fixed array and std::array in the above snippet. Still the member functions should take up additional space, correct?

        • Alex

          No, functions are just code, they don't take additional space on a per-object basis.

          Functions do increase the size of your executable though, which means it will require more memory to load.

      • Ivar

        Perhaps because std::array has information about its size? (At least, that led me to think it would take up more space.) But according to the C++ reference, the size "is a template parameter, fixed on compile time", and not actually stored in the array object. Still, wouldn't this mean that each std::array uses more memory than a regular array, although in a different location than the array itself?

        • Alex

          Nope. std::array (along with many other classes) is implemented as a template classes. When you define a std::array, the compiler custom builds you a new std::array class with data of type int and hardcoded size of 10. That 10 is baked into the class definition, so it doesn't take any extra room.

          We cover template classes in more detail in chapter... 14.

  • Reaversword

    About arrays lesson, there is no info about arrays destruction.

    Arrays auto delete themselves when they go out of scope (as vectors do)?, or we must take care of use "delete[] our_array;" when we're dealing with them?.

    Thanks for your wondeful guide Alex.

    • Alex

      Much like you don't have to clean up after a fixed array, there's no need to clean up a std::array either. I've added a mention of that into the lesson.

  • Jeff

    Hi Alex, I've been following this tutorial and find it extremely helpful. To be honest it's better than any text or videos I've ever read or seen. Definitely worth recommendation to my friends.
    Do you have any tutorials on other programming languages? I really like the way you explain all those concepts and like to learn more once finish with c++.

    • Alex

      Unfortunately, no. I've been focusing my limited time on improving/expanding these lessons instead of branching out into new languages.

      Better to do one thing well than two things mediocrely.

      • Darren

        "Better to do one thing well than two things mediocrely." *

        *Ah "multi-tasking". Being good at multi-tasking is like saying "I'm good at doing many things poorly but at the same time".

  • heidi

    So glad to see you are updating this site again Alex! Great tutorial as ever!
    I have a minor suggestion: the example would be easier to understand if you name the first array as "array1" instead of just "array"
    The name "array" is purple in colour and looks like a part of the declaration syntax to a beginner.

    • Alex

      Thanks for pointing this out.

      "array" being highlighted as a keyword is actually a bug in the syntax highlighter (as it's not a keyword in C++). I've modified the list of keywords in the plugin to remove "array" from the list so it shouldn't highlight any more.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]