DevX HomePage

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

Migrate your fixed-sized sequences to std::array, which offers a secure, efficient, and convenient alternative to built-in arrays—sans the overhead of vector.
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:

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 <array>, and it supports random access iterators. An instance of array<T, N> 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 <array> 

std::array <int,5> 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 <int> 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 = a.data(); //OK
const int* pc = a.data(); //OK
Similarly, std::array blocks implicit derived-to-base conversions, which might be quite dangerous:
struct Dog : Animal { /* ... */ };
struct Cat : Animal { /* ... */ };

void trap(array<Animal*,5>& animals)
{
 animals[3] = new Cat;
};

array<Dog*,5> dogs;
trap(dogs); /*error: can't convert array<Dog*,5> to
             array<Animal*,5>; */
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<int,5>* parr)
{
 cout<< parr->size() <<endl; //output 5
 return parr->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 <int,5> myints;
myints::size_type sz = a.size();
myints::iterator it = a.begin();
while (it++ != a.end())
  cout<<*it<<endl;
To assign a single value to every element in the array, use the fill() member function:
array<int,5> 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<Container C> C::value_type sum(const C& c)
{
 return accumulate(c.begin(),c.end(),0);
}

array<int,5> ai5={0,2,4,8,10};
vector<int> vi={0,1,3};
// ...
int sum1 = sum(ai5);
int sum2 = sum(vi);
Unlike with built-in arrays, a zero-length std::array is valid, albeit with certain restrictions:
array<int,0> 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 = a0.data(); //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.

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of 'The ANSI/ISO Professional C++ Programmer's Handbook' and 'The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++.'


DevX is a division of Internet.com.
© Copyright 2010 Internet.com. All Rights Reserved. Legal Notices