std::array: The Secure, Convenient Option for Fixed-Sized Sequences

std::array: The Secure, Convenient Option for Fixed-Sized Sequences

hen implementing a sequence of elements that needs to grow and shrink dynamically, std::vector is a fine choice. It provides the convenience of a standard container class, including automatic memory management, random access to elements, a uniform interface, and compatibility with standard algorithms.

However, for a sequence whose size is fixed, the performance hit that comes with all that convenience isn’t always justifiable. In particular, a vector incurs the following overhead:

  • Nontrivial initialization and destruction. The constructor and destructor of std::vector are relatively costly. This overhead is particularly noticeable when your program creates a large number of vectors.
  • Allocation time. Vectors allocate storage for their elements at runtime.
  • Space overhead. A vector object typically occupies 32 bytes.

Built-in arrays carry none of this overhead. They allocate their storage statically and have zero space overhead. So why not just use built-in arrays instead for your fixed-sized sequences? Built-in arrays have their own downside: Their security loopholes make them an insecure choice.

Luckily, the C++ Standard Library offers a container-like template called std::array, which offers a secure, efficient, and convenient alternative to built-in arrays?without the overhead of vectors. This 10-Minute Solution shows how to use this powerful alternative for fixed-sized sequences.

How can I implement fixed-sized sequences without the security loopholes of built-in arrays or the noticeable overhead of vectors?

Use std:array as a secure, efficient, and convenient alternative to built-in arrays and vectors for your fixed-sized sequences.

Instantiation and Usage

The std::array class template is defined in the standard header , and it supports random access iterators. An instance of array stores N elements of type T. The elements are stored contiguously on the stack (as opposed to std::vector, which stores elements on the free-store). Also, std::array has implicitly-declared special member functions (constructor, destructor, copy constructor, and assignment operator) with minimal runtime overhead.

You instantiate an array object like this:

#include  std::array  a={1,2,3};

The first template argument specifies the type of the elements. The second argument specifies the array’s size. Notice that the size is mandatory; you can’t deduce it from an initializer-list:

std::array  a2={1,2,3}; //error, size missing

The initializer-list is a comma-separated list of up to N elements whose types are convertible to T. If the initializer list contains fewer initializers than N, the remaining elements are default-initialized. Thus, in the example above, a[3] and a[4] are initialized to zero.

Security Enhancements

With respect to security, std::array doesn’t implicitly convert to a pointer. This is to protect your code from inadvertent pointer-related bugs, which are so pervasive when using built-in arrays. If you want to convert std::array to a pointer, you must use the data() member function:

int* p = a; //error, no implicit conversion to int*int* p2 =; //OKconst int* pc =; //OK

Similarly, std::array blocks implicit derived-to-base conversions, which might be quite dangerous:

struct Dog : Animal { /* ... */ };struct Cat : Animal { /* ... */ };void trap(array& animals){ animals[3] = new Cat;};array dogs;trap(dogs); /*error: can't convert array to             array; */

If this implicit conversion were allowed, dogs[3] would now contain Cat.

Finally, unlike built-in arrays, which decay into pointers at the slightest pretext and thus lose track of their size, std::array always knows how many elements it contains:

int probe(const array* parr){ cout<< parr->size() <size();}

Interfaces to the Standard Library

The std::array template provides the same interface as a standard container class. Therefore, you can use the uniform type names iterator, const_iterator, reference, size_type, difference_type, value_type, and so on:

typedef std::array  myints;myints::size_type sz = a.size();myints::iterator it = a.begin();while (it++ != a.end())  cout<<*it<

To assign a single value to every element in the array, use the fill() member function:

array arr; //no initialize list,arr.fill(12); //assign the value 12 to every element

All standard algorithms operate on std::array directly, as with vectors. Consider a function template sum(). It takes a type T that meets the container concept requirements and sums up its elements:

template C::value_type sum(const C& c){ return accumulate(c.begin(),c.end(),0);}array ai5={0,2,4,8,10};vector vi={0,1,3};// sum1 = sum(ai5);int sum2 = sum(vi);

Unlike with built-in arrays, a zero-length std::array is valid, albeit with certain restrictions:

array a0; //OK, no elements

The C++ standard guarantees that when N == 0, begin() == end() == unique value. However, the return value of data() is unspecified, as are the effects of calling front() and back() for a zero-sized array:

int* p =; //unspecified; don't do that

As with other standard containers, the member function empty() reports whether the array is empty:

bool has_data =a0.empty();

Compiler Support

The new std::array class template is now supported by several leading compilers, so you should consider using it as an efficient alternative to vectors when dealing with fixed-sized sequences.

To enable C++09 features, you may need to turn on special compilation options, for example, -std=c++0x on GCC. Check your compiler's online documentation for specific details.


About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist