Arrays
Arrays are the simplest C++ container for storing ordered data of a uniform type.
Two types of array are available:
- Basic arrays as defined in the C programming language.
- The enhanced
std::array
from the C++ Standard Library.
💡 Best Practice:
Unless your collection size is fixed, std::vector
should be preferred over arrays.
💡 Best Practice:
With Unreal Engine use the TArray
container class in place of arrays and vectors.
Table of Contents
- C-Style Arrays
- C-Style Arrays Definition
- C-Style Array Set and Get
- C-Style Array Length
- Copying C-Style Arrays
- The C++ Standard Array
- Defining Standard Arrays
- Standard Array Length
- C-Style vs Standard Array
- Out-of-Bounds Behaviour
- Looping Over Standard Arrays
- Copying Arrays
- Standard Arrays as Function Arguments
- Passing Arrays by Reference
- Vector > Standard Array > C-Style Arrays
- Further Reading
C-Style Arrays
As the name implies, C-Style Arrays are arrays as defined in the C programming language.
They are only presented here because you may run into them in legacy C++ code.
💡 Best Practice:
Avoid using C-Style Arrays in C++.
C-Style Arrays Definition
C-Style Arrays are defined with a type and a length.
int primes[4]{}; // An array of four ints.
Arrays can be initialized when declared:
int primes[4]{2, 3, 5, 7};
🎵 Note:
Array length cannot be changed once defined.
C-Style Array Set and Get
We can store and retrieve data into the array positions using zero-base indexes and square braces:
int primes[4]{}; // An array of four ints.
primes[0] = 2; // First element has index 0
primes[1] = 3;
primes[2] = 5;
primes[3] = 7; // Last element has index 3 (length-1)
// Retrieve array elements by position:
int sum = primes[0] + primes[1] + primes[2] + primes[3]
C-Style Array Length
The length of an array can be retrieve using std::size()
from the <iterator>
header:
#include <iterator>
int main() {
int fibonacci[7]{1, 1, 2, 3, 5, 8, 13};
int length = std::size(fibonacci);
}
âš¡ Warning:
The std::size()
function won’t work on arrays passed as arguments to functions.
Copying C-Style Arrays
C-Style arrays are not copied by using the assignment operator:
double copy[4]{1,2,3,4};
double pasta[4];
// This will not make a copy:
pasta = copy; // Compiler Error: Array type is not assignable.
Instead we need to use std::copy
from the <algorithm>
header:
std::copy(std::begin(copy), std::end(copy), std::begin(pasta));
The C++ Standard Array
std::array
was designed as a zero-overhead wrapper for C-Style Arrays.
Standard Array includes the following enhancements over C-Style Arrays:
- Easily assigned and copied.
- Length can be determined when passed into a function.
- The length and type can be inferred when initialized during declaration.
💡 Best Practice:
Always prefer std::array
over C-Style arrays. Lots to gain, little to lose.
Defining Standard Arrays
To use a standard array we must first include the correct header:
#include <array>
Standard arrays are defined with a type and a size:
// Array of five integers
std::array<int, 5> evenNumbers;
The type and size can be inferred if an initializer list is provided:
std::array evenNumbers{2, 4, 6, 8, 10};
🎵 Note:
Uninitialized array positions default to a value of zero.
Standard Array Length
A standard array can be queried for its own length using the size()
method.
std::array evenNumbers{2, 4, 6, 8, 10};
int length = evenNumbers.size();
C-Style vs Standard Array
Here’s a program that demonstrates some of the differences between std::array
and C-Style Arrays.
Out-of-Bounds Behaviour
Both C-Style and Standard Arrays are missing array boundary checking. Historically this has been (and continues to be) a major source of bugs and security exploits.
💡 Best Practice:
Manually include guards in your code to prevent out-of-bounds reads or writes.
Looping Over Standard Arrays
The two simplest ways to loop over standard arrays:
🎵 Note:
The loop variable i
will be of type std::size_t
. More on this type.
Copying Arrays
An easier way to copy arrays is to use the array copy constructor:
std::array arrayOne{ 3, 1, 4, 1, 5, 9};
std::array arrayTwo{ arrayOne }; // Copy arrayOne into arrayTwo.
Standard Arrays as Function Arguments
Standard Arrays can be received by function parameters.
Unlike C-Style Arrays, Standard Arrays don’t lose their length information once inside the function.
double calculateAverage(std::array<double, 5> data) {
double sum{0.0};
for (auto number : data) {
sum += data;
}
return sum / data.size();
}
🎵 Note:
When passing a Standard Array to a function, a copy of the array will be made.
Passing Arrays by Reference
C++ functions are pass-by-value by default, meaning copies are made of the arguments passed to a function.
We can switch to pass-by-reference with the &
operator. Passing a reference to an argument avoids the performance hit of the copy.
// Array passed as a reference for performance and as a const for safety:
double calculateAverage(const std::array<double, 5>& data) {
// Identical function body as above.
}
💡 Best Practice:
For safety, we mark reference arguments as immutable using const
.
Without the const
we might accidentally change the array while in the function, affecting the referenced array outside of the function.
Vector > Standard Array > C-Style Arrays
Above we stated that you should prefer Standard Arrays over C-Style Arrays.
C++ also has a collection type called a Standard Vector, which is similar to a std::array
, but without a fixed length. We’ll cover vectors in the next section.
💡 Best Practice:
Unless your collection length is fixed, prefer std::vector
over std::array
.