Sequence Containers std::array in C++

Anatomy of std::array:

std::array is part of the Standard Template Library (STL) in C++ and provides a modern alternative to the traditional C-style arrays. It encapsulates a fixed-size, statically allocated arrays with several benefits, including bounds checking, improved syntax, and compatibility with other STL algorithms and containers.

The array is a collection of homogeneous objects and this array container is defined for constant size arrays or (static size). This container wraps around fixed-size arrays and the information of its size are not lost when declared to a pointer.

In order to use the standard template array, we need to include the array header:

#include <array>

Declaration and Initialization:

Defining an std::array involves specifying the type and size. Here's a basic example:

#include <array>

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

This creates an integer array with a size of 5, initialized with the values 1 through 5.

  • std::array is declared and initialized using the syntax std::array<type, size> arrayName = {elements};

Size and Capacity:

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

// Size and Capacity
std::cout << "Size: " << myArray.size() << std::endl;        // 5
std::cout << "Max Size: " << myArray.max_size() << std::endl; // Implementation-defined maximum size
  • The size() method returns the number of elements in the array.
  • max_size() returns the maximum number of elements the array can hold (implementation-defined).

Iterating through std::array:

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

// Iterating through std::array
for (const auto& element : myArray) {
    std::cout << element << " ";
}
  • Range-based for loop simplifies iteration through the elements of the array.
  • Use auto to automatically deduce the type of elements.

Element Acces and Modification:

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

// Accessing and modifying elements
myArray[2] = 10; // Modifying the third element
int value = myArray.at(3); // Accessing the fourth element
  • Elements can be accessed and modified using the array subscript operator [] or the at() method.
  • at() performs bounds checking and throws std::out_of_range if the index is out of bounds.

Key Features of std::array:

1. Size and Bound Checking

Unlike traditional arrays, std::array knows its size and provides a size() member function. Additionally, it performs bounds checking, throwing an std::out_of_range exception if an attempt is made to access an element outside the array's bound.

std::array<int, 3> myArray = {1, 2, 3};
std::cout << "Size: " << myArray.size() << std::endl;

// Accessing elements safely
try {
    int value = myArray.at(4); // Throws an exception
} catch (const std::out_of_range& e) {
    std::cerr << "Out of range exception: " << e.what() << std::endl;
}

2. Iterators

std::array supports iterators, allowing for convenient traversal of its elements. You can use standard iterators like begin(), end(), rbegin(), and rend().

std::array<int, 3> myArray = {1, 2, 3};

for (auto it = myArray.begin(); it != myArray.end(); ++it) {
    std::cout << *it << " ";
}

Functions

1. Element Access Functions:

at(index):

  • Returns a reference to the element at the specified index.
  • Performs bounds checking and throws an std::out_of_range exception if index is out of bounds.

operator[](index):

  • Returns a reference to the element at the specified index.
  • No bounds checking is performed; users must ensure index is within bounds.

Example:

#include <array>
#include <iostream>

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

// Using at() with bounds checking
try {
    int value = myArray.at(2); // Accessing element at index 2
    std::cout << "Value at index 2: " << value << std::endl;
} catch (const std::out_of_range& e) {
    std::cerr << "Out of range exception: " << e.what() << std::endl;
}

// Using operator[] without bounds checking
int value = myArray[3]; // Accessing element at index 3
std::cout << "Value at index 3: " << value << std::endl;

front():

  • Returns a reference to the first element in the array.

back():

  • Returns a reference to the last element in the array.

Example:

#include <array>
#include <iostream>

std::array<int, 4> myArray = {10, 20, 30, 40};

// Accessing the first and last elements
std::cout << "First element: " << myArray.front() << std::endl;
std::cout << "Last element: " << myArray.back() << std::endl;

2. Iterator Functions:

begin():

  • Returns a iterator pointing to the first element in the array.

end():

  • Returns an iterator pointing one past the last element in the array.

Example:

#include <array>
#include <iostream>

std::array<int, 3> myArray = {100, 200, 300};

// Using iterators to traverse the array
for (auto it = myArray.begin(); it != myArray.end(); ++it) {
    std::cout << *it << " ";
}
std::cout << std::endl;

rbegin():

  • Returns a reverse iterator pointing to the last element in the reversed array.

rend():

  • Returns a reverse iterator pointing one position before the first element in the reversed array.

Example:

#include <array>
#include <iostream>

int main(){

	std::array<int, 3> myArray = {10, 20, 30};

	// Using reverse iterators to traverse the array in reverse
	for (auto rit = myArray.rbegin(); rit != myArray.rend(); ++rit) {
    	std::cout << *rit << " ";
	}
	std::cout << std::endl;
	return 0;
}

// Output
30 20 10

3. Capacity Functions:

size():

  • Returns the number of elements in the array.

empty():

  • Returns true if the array is empty, false otherwise.

4. Modifiers Functions:

fill(value):

  • Sets every element in the array to the specified value.
#include <array>
#include <iostream>

int main(){
	std::array<int, 4> myArray;

	// Filling the array with a specific value
	myArray.fill(42);

	for (int value : myArray) {
    	std::cout << value << " ";
	}
	std::cout << std::endl;
	return 0;
}

// Output
42 42 42 42

swap(other):

  • Swaps the contents of the array with another of the same type and size.
#include <array>
#include <iostream>

int main(){

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

    // Swapping the contents of two arrays
    array1.swap(array2);

    // Displaying the contents of array1
    for (int value : array1) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    // Displaying the contents of array2
    for (int value : array2) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
    return 0;
}

// Output
4 5 6
1 2 3

Advantages Over C-Style arrays:

  1. Type safety: std::array includes type information, preventing accidental misuse.
  2. Bounds checking: at() provides runtime bounds checking, enhancing safety.
  3. Size retrieval: size() provides a convenient way to obtain the size of the arrays.