Modern C++:Efficient and Scalable Application Development
上QQ阅读APP看书,第一时间看更新

Using the stack-based array class

The array class is defined in the <array> header file. The class allows you to create fixed sized arrays on the stack and, as with built-in arrays, they cannot shrink or expand at runtime. Since they are allocated on the stack, they do not require a call to a memory allocator at runtime, but clearly, they should be smaller than the stack frame size. This means that an array is a good choice for small arrays of items. The size of an array must be known at compile time and it is passed as a template parameter:

    array<int, 4> arr { 1, 2, 3, 4 };

In this code, the first template parameter in the angle brackets (<>) is the type of each item in the array, and the second parameter is the number of items. This code initializes the array with an initialize list, but note that you still have to provide the size of the array in the template. This object will work like a built-in array (or indeed, any of the Standard Library containers) with ranged for:

    for (int i : arr) cout << i << endl;

The reason is that array implements the begin and end functions that are required for this syntax. You can also use indexing to access items:

    for (int i = 0; i < arr.size(); ++i) cout << arr[i] << endl;

The size function will return the size of the array and the square bracket indexer gives random access to members of the array. You can access memory outside of the bounds of the array, so for the previously defined array that has four members, you can access arr[10]. This may cause unexpected behavior at runtime, or even some kind of memory fault. To guard against this, the class provides a function, at, which will perform a range check and if the index is out of range the class will throw the C++ exception out_of_range.

The main advantage of using an array object is that you get compile-time checks to see if you are inadvertently passing the object to a function as a dumb pointer. Consider this function:

    void use_ten_ints(int*);

At runtime, the function does not know the size of the buffer passed to it, and in this case the documentation says that you must pass a buffer with 10 int type variables, but, as we have seen, C++ allows a built-in array to be used as a pointer:

    int arr1[] { 1, 2, 3, 4 }; 
use_ten_ints(arr1); // oops will read past the end of the buffer

There is no compiler check, nor any runtime check to catch this error. The array class will not allow such an error to happen because there is no automatic conversion into a dumb pointer:

    array<int, 4> arr2 { 1, 2, 3, 4 };  
use_ten_ints(arr2); // will not compile

If you really insist in obtaining a dumb pointer, you can do this and be guaranteed to have access to the data as a contiguous block of memory where the items are stored sequentially:

    use_ten_ints(&arr2[0]);    // compiles, but on your head be it 
use_ten_ints(arr2.data()); // ditto

The class is not just a wrapper around a built-in array, it also provides some additional functionality. For example:

    array<int, 4> arr3; 
arr3.fill(42); // put 42 in each item
arr2.swap(arr3); // swap items in arr2 with items in arr3