Loading...

std array container analysis

In C++, the std::array is a container class template defined in the Standard Library (part of the C++ Standard Template Library, or STL) that provides a fixed-size array with several advantages over traditional C-style arrays

Why std::array introduced

When you pass a C-style (an array declared using square brackets[]) to a function in C or C++, you are actually passing a pointer to the first element of the array, and the size information gets lost.

Passing the array to a function:

When you pass a C-style array to a function, you are effectively passing the memory address (pointer) of the first element of the array. This pointer points to the memory location where the array's data begins.

void myFunction(int arr[], int size) {
    // ...
}

int main() {
    int myArray[5] = {1, 2, 3, 4, 5};
    myFunction(myArray, 5); // Pass the array to the function
    // ...
}

Loss of Size Information:

Inside the function, you receive the pointer to the array's first element but not the size of the array. You need to explicitly pass the size as a separate argument to the function to work with the array's elements safely.

void myFunction(int arr[], int size) {
    // Here, 'size' tells you how many elements are in the array 'arr'.
    // ...
}

Due to this loss of size information, its important to be careful when working with C-style arrays in functions. If you access elements beyond the bounds of the array, it can lead to undefined behavior, which is a common source of bugs and security vulnerabilities. This is one of the reasons why C++ introduced the std::array and the STL container, which provide safer and more convenient alternatives with built-in size informatiion and bounds checking.

Guide:

Header File:

To use std::array , you need to include the <array> header.

#include <array>

Declaration:

You declare a std::array by specifying its data type, name, and size of template parameters.

std::array<DataType, Size> myArray;

For example, to declare an integer array of size 5.

std::array<int, 5> myIntArray;

Initialization:

You can initialize a std::array at the time of declaration using a list of values enclosed in curly braces.

std::array<int, 5> myIntArray = {1, 2, 3, 4, 5};

Alternatively, you can use uniform initialization:

std::array<int, 5> myIntArray {1, 2, 3, 4, 5};

Accessing Elements:

You can access elements of a std::array using the [] operator, just like with traditional arrays.

int value = myIntArray[2]; // Access the third element (index 2)

Size:

The size of a std::array is fixed and can be obtained using its size() member function.

int size = myIntArray.size(); // Returns 5

Iterating:

You can use range-based for loops to iterate over the elements of a std::array.

for (const auto& element: myIntArray){
	// Access and manipulate each element
}

Benefits 

  • std::array provides benefits like type safety, bound checking, better compatibility with standard algorithms and containers compared to C-style arrays.
  • It also includes member functions for various operations, like sorting and swapping.
// Sort the elements
std::sort(myIntArray.begin(), myIntArray.end());

Performance:

Typically std::array has the same performance characteristics as C-style arrays since it's implemented as a contiguous block of memory. It's more efficient than some dynamically resizable containers like std::vector when the size is known and fixed.

 

Most Commonly used member functions of std::array.

at(index):

  • Returns a reference to the elements at the specified index.
  • Performs bounds checking, throwing an std::out_of_range exception if the index is out of bounds.
std::array<int, 5> arr = {1, 2, 3, 4, 5};
int value = arr.at(2); // Access the element at index 2

operator[]:

  • Returns a reference to the element at the specified index.
  • Does not perform bounds checking, so be cautious when using it.
int value = arr[2]; // Access the element at index 2.

front():

  • Returns a reference to the first element in the array.
int first = arr.front(); // Access the first element

back():

  • Returns a reference to the last element in the array.
int last = array.back(); // Access the last element.

data():

  • Returns a pointer to the underlying array.
  • Useful when interfacing with C-style functions that a pointer to an array.
int *ptr = arr.data(); // Get a pointer to the underlying array.

size():

  • Returns the number of elements in the array.
int size = arr.size(); // Get the size of the array

empty():

  • Returns true if the array is empty (size is zero), otherwise false.
  • Returns 1 if the length of array is 0 and 0 if not.
bool isEmpty = arr.empty(); // Check if the array is empty

fill(value):

  • Sets all elements of the array to the specified value.
arr.fill(0); // Set all elements to zero

swap(other):

  • Exchanges the contents of the array with another array of the same type and size.
std::array<int, 5> anotherArr = {6, 7, 8, 9, 10};
arr.swap(anotherArr); // Swap the contents of arr and anotherArr

max_size():

This function returns the maximum number of elements that the std::array can hold.

Note that the max_size() function returns a theoretical limit, which may not be achievable in practice due to factors like available memory.

std::array<int, 5> myArray;
size_t maxSize = myArray.max_size(); // The maximum possible size (depends on the implementation)

Iterators

Instead of indices, we can also use iterators to iterate over container. An iterator is a kind of pointing item which can be pointed to an element of a container and has the ability to iterate over the container. It means that if we have an iterator at the beginning of an std::array then, it can go over the entire std::array pointing each item of the std::array.

begin() and end():

  • Returns iterators pointing to the first and one-past-the-end elements of the array, respectively.
  • Useful for iterating over the elements using range-based for loops or in algorithms.
for (auto it = arr.begin(); it != arr.end(); ++it){
	// Access and manipulate each element using 'it'
}

rbegin:

  • rbegin() - returns a reverse iterator pointing to the last element of the container (the element at the end).
  • It allows you to traverse the std::array in reverse order, starting from the last element and moving towards the first element.
  • This is particularly useful when you need to iterate over a container in reverse without modifying its contents.
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
auto rIter = myArray.rbegin();

// Iterate in reverse order
while (rIter != myArray.rend()) {
    std::cout << *rIter << " ";
    ++rIter;
}
// Output: 5 4 3 2 1

rend:

  • rend() returns a reverse iterator pointing to the position before the first element of the std::array.
  • It marks the end of the reverse iteration and is often used as stopping condition in loops that traverse a container in reverse.
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
auto rBegin = myArray.rbegin();
auto rEnd = myArray.rend();

// Iterate in reverse order using rBegin and rEnd
while (rBegin != rEnd) {
    std::cout << *rBegin << " ";
    ++rBegin;
}
// Output: 5 4 3 2 1