Array

Hi everyone ✋

In this tutorial we will talk about Array

So, What is Array actually?

Array is a sequential container of C++ STL that wraps a fixed-size contiguous array. The size of an array is decided at compile time and cannot be changed once the array is declared.

We all know the classic C-style array (int arr[10];). STL array is basically a thin wrapper around it — with the same fixed-size nature, the same contiguous memory layout, and the same O(1) random access. But unlike the C-style array, STL array gives us proper STL-style methods like size(), front(), back(), begin(), end(), and so on. It also knows its own size (C-style arrays forget their size the moment you pass them to a function).

Because STL array has a fixed size, it does not have methods like push_back(), pop_back(), insert(), erase(), or resize(). If we need to grow or shrink, we should use vector or deque instead.

Array’s underlying data structure is a plain C-style array. There is no extra pointer or heap allocation — the data sits right inside the array object itself, so it is typically allocated on the stack.

💡 Note on availability — STL array is a C++11 feature. Any modern compiler supports it with the -std=c++11 flag (or newer).

Header File Inclusion for array

#include <array>

Declaration & Initialization

An STL array takes two template parameters — the element type, and the fixed size.

Declaring an uninitialized array —


array <int, 5> mark;

Here, the element type is int and the size is 5. The elements are uninitialized (they will contain garbage values until we assign to them).

Declaring an array with values —


array <int, 5> mark = { 85, 90, 78, 92, 88 };

After Initialization mark will look like this —

 

85 90 78 92 88

 

Declaring an array with fewer values than size —

If we provide fewer values than the declared size, the remaining elements are value-initialized (zero for built-in types) —


array <int, 5> mark = { 85, 90 };

After Initialization mark will look like this —

 

85 90 0 0 0

 

Declaring a zero-initialized array —

We can zero-initialize the whole array by giving it an empty initializer list —


array <int, 5> mark = {};

All five elements will be 0.

Declaring arrays of different types —

Element type can be anything —


array <double, 4> scores = { 95.5, 88.0, 72.5, 60.0 };
array <string, 3> nameList = { "Imran", "Linkon", "Sakib" };
array <pair<int, int>, 2> points = { {1, 2}, {3, 4} };

💡 Quick tip on size — The size of an STL array is part of its type. That means array<int, 5> and array<int, 6> are two completely different types, and we cannot assign one to the other.

Accessing the element

[ ] subscript operator

Just like a C-style array, STL array supports the [ ] subscript operator for random access —


array <int, 5> mark = { 85, 90, 78, 92, 88 };

// the following line will print 78 as output
cout << mark[2] << endl;

// the following line will print 85 as output
cout << mark[0] << endl;

at() method

For accessing an element, at() method works the same as the [ ] operator — but with bounds checking. If we pass an index out of range, at() throws an out_of_range exception, while [ ] gives us undefined behavior.


// the following line will print 78 as output
cout << mark.at(2) << endl;

// the following line will throw out_of_range exception
cout << mark.at(10) << endl;

at() is also useful for pointer variables, since pointer variables can not use [ ] subscript operator directly —


array <int, 5> *pArr = &mark;

// the following line will print 78 as output
cout << pArr->at(2) << endl;

front() and back()

We can easily access the first and last element of an array using front() and back() methods —


// front() method for accessing the first element
// the following line will print 85 as output
cout << mark.front() << endl;

// back() method for accessing the last element
// the following line will print 88 as output
cout << mark.back() << endl;

data() method

data() returns a raw pointer to the first element of the underlying C-style array. This is useful when we need to pass the array to a C API or a function that expects a plain pointer —


int *rawPtr = mark.data();

// now rawPtr points to mark[0]
cout << rawPtr[0] << endl;
cout << rawPtr[3] << endl;

Output will be —


85
92

Modifying the elements

Since STL array has a fixed size, we cannot add or remove elements. But we can freely modify the existing ones — using the [ ] operator, at() method, front(), or back() —


array <int, 5> mark = { 85, 90, 78, 92, 88 };

mark[0] = 100;
mark.at(2) = 80;
mark.back() = 95;

After modification mark will look like this —

 

100 90 80 92 95

 

fill() method

fill() is a handy method that assigns the same value to every element of the array in one call —


array <int, 5> mark;

mark.fill(0);

After fill(0) mark will look like this —

 

0 0 0 0 0

 

This is especially useful when we want to reset a counting array or a visited array to 0 or some default value.

Size and Empty


array <int, 5> mark = { 85, 90, 78, 92, 88 };

cout << mark.size() << endl;
cout << mark.max_size() << endl;

if (mark.empty())
{
    cout << "Array is empty" << endl;
}
else
{
    cout << "Array is not empty" << endl;
}

Output will be —


5
5
Array is not empty

💡 Note on size(), max_size(), and empty() — Since the size of an STL array is fixed at compile time, size() and max_size() always return the same value. And empty() returns true only when the array size is 0 (declared as array<int, 0>) — for a non-zero-sized array, it always returns false.

Iterating through an array

Range-based for loop

The cleanest way to iterate through an array is using a range-based for loop —


array <int, 5> mark = { 85, 90, 78, 92, 88 };
for (auto &value : mark)
{
    cout << value << " ";
}

Output will be – 85 90 78 92 88

Using index

Just like a C-style array, we can iterate with a simple for loop and indices —


for (int i = 0; i < mark.size(); i++)
{
    cout << mark[i] << " ";
}

Using iterator

We can also iterate using iterators directly —


array <int, 5>::iterator it;

for (it = mark.begin(); it != mark.end(); it++)
{
    cout << *it << " ";
}

Swapping

swap() method

STL array has a method named swap(), which swaps values element-by-element between two arrays. The two arrays must have the same type and the same size


array <int, 4> arrOne = { 1, 2, 3, 4 };
array <int, 4> arrTwo = { 10, 20, 30, 40 };

arrOne will look like this —

 

1 2 3 4

 

arrTwo will look like this —

 

10 20 30 40

 

Now, let’s swap the elements of two arrays —


// swapping values between two arrays
arrOne.swap(arrTwo);

After Swapping arrOne will look like this —

 

10 20 30 40

 

After Swapping arrTwo will look like this —

 

1 2 3 4

 

💡 Note on swap() cost — Unlike vector or deque (where swap is O(1) because they only swap internal pointers), array’s swap() is O(n). Since the elements live directly inside the array object, swap has to actually copy each element one by one.

Array Object Operations

Copying an array to another

For copying an array to another, we can simply use the assignment operator —


array <int, 4> oldArr = { 1, 2, 3, 4 };
array <int, 4> newArr;

// now copying all oldArr elements to newArr
newArr = oldArr;

Comparing two arrays

Array supports all comparison operators — ==, !=, <, >, <=, >=. Two arrays are compared element-by-element —


array <int, 3> arrOne = { 1, 2, 3 };
array <int, 3> arrTwo = { 1, 2, 3 };
array <int, 3> arrThree = { 1, 2, 4 };

if (arrOne == arrTwo)
{
    cout << "arrOne and arrTwo are equal" << endl;
}

if (arrOne < arrThree)
{
    cout << "arrOne is less than arrThree" << endl;
}

Output will be —

arrOne and arrTwo are equal
arrOne is less than arrThree

Structured Bindings (C++17)

Since C++17, STL array plays nicely with structured bindings — we can unpack the array into individual named variables in a single line —


array <int, 3> point = { 10, 20, 30 };

auto [x, y, z] = point;

cout << x << " " << y << " " << z << endl;

Output will be – 10 20 30

This is especially handy when we return an array from a function and want to name the individual values right at the call site.

Tuple Interface

STL array also supports the tuple interface — we can use std::get<N>(), std::tuple_size, and std::tuple_element on it, just like a tuple —


array <int, 3> point = { 10, 20, 30 };

// get the element at compile-time index 1
cout << get<1>(point) << endl;

// get the size at compile time
cout << tuple_size<decltype(point)>::value << endl;

Output will be —


20
3

💡 Quick tip on get vs [ ]get<N>() uses a compile-time index, while [ ] uses a run-time index. This means get<N>() can catch out-of-range errors at compile time, while [ ] can only fail at run time.

Array vs C-style array vs Vector

This is the biggest question when picking between these three — so it is worth laying them side by side.

 

Property array C-style array vector
Size Fixed at compile time Fixed at compile time Dynamic (changes at run time)
Memory location Typically stack Typically stack Heap (pointer on stack)
Knows its own size Yes (size() method) No (decays to pointer) Yes (size() method)
STL iterator support Full Via raw pointers Full
Bounds checking at() throws None at() throws
Copy with = Yes (element-wise) No (pointer copy only) Yes (deep copy)
Runtime overhead vs raw array Zero Baseline Small (heap allocation)
Use when Size is known at compile time and we want STL features Working with legacy code or C APIs Size is dynamic or unknown

 

Time Complexity

 

Operation Description Time Complexity
[ ] or at() Random access O(1)
front() Accessing the first element O(1)
back() Accessing the last element O(1)
data() Returns a raw pointer to the first element O(1)
begin() / end() Iterators to the beginning and end O(1)
rbegin() / rend() Reverse iterators O(1)
size() Returns the fixed size of the array O(1)
max_size() Returns the maximum number of elements (equal to size) O(1)
empty() Returns true if array size is 0 O(1)
fill() Assigns the same value to every element O(n)
swap() Swap elements between two arrays O(n)
== / != / < / > / <= / >= Element-wise comparison O(n)
get<N>() Compile-time indexed access O(1)

 

Applications

        • Storing a fixed set of values that never change size (e.g., days of week, RGB colors, chess board)
        • Lookup tables and sine/cosine tables computed at program start
        • Visited arrays and counting arrays in competitive programming when the size is known
        • Representing mathematical entities with a fixed dimension (2D points, 3D vectors, matrices)
        • Passing a known-size buffer to a C API through the data() pointer
        • Embedded systems and memory-constrained environments (no heap allocation)
        • Drop-in replacement for C-style arrays when we want STL features like size() and bounds checking
        • Returning multiple values from a function as a single named unit

In the next tutorial we will talk about another useful STL container.

Until then
Happy Coding 💻 🎵

Leave a Comment

Your email address will not be published. Required fields are marked *