In this article we will about study C-style array vs std::array. A std::array should have same run-time performance as a c-style array. In STL there are two type of arrays, first is fixed length array means std::array and other type is dynamic array means std::vector.
Introduced in C++11, std::array has a unique characteristic among all sequential containers of the STL, you can not adjust it size during run-time.
Initialization of std::array
std::array initialized by following ways:
// Required header file #include <array> // Declare an integer array with length 4 std::array<int, 4> myArray;
// Initialization list
std::array<int, 5> myArray = { 9, 8, 5, 3, 1 };
// Uniform initialization
std::array<int, 5> myArray { 9, 8, 5, 3, 1 };
// The 10 elements are not initialized. std::array<int,10> myArray ;
The 10 elements are value-initialized to zero.
std::array<int,10> myArray {};
// Legal, elements 3 and 4 are set to zero!
std::array<int> myArray = { 9, 7, 5};
// Illegal, array length must be provided
std::array<int, > myArray = { 9, 8, 5, 3, 1 };
// Illegal, too many elements in initializer list!
std::array<int, > myArray = { 0, 1, 2, 3, 4, 5 };
Index access
std::array supports the index access in 3 ways :
- myArray[n-1]: Access to the nth element without a check of the array boundaries.
- myArray.at(n-1): Access to the nth element with a check of the array boundaries. Eventually, a std::range_error exception is thrown.
- std::get
(myArray): Access to the nth element with a check of the array boundaries at compile time. The syntax is according to std::tuple. std::get (myArray) shows the relationship of std::array with std::tuple. std::array is a homogeneous container of fixed size while std::tuple is a heterogeneous container of fixed size.
Example: C-Style array Vs std::array
#include <iostream>
#include <array>
#include <vector>
int main()
{
// c-style array
int array1[3] = {1, 2, 3};
array1[1] = 15;
std::cout << "size: " << (sizeof(array1) / sizeof(*array1)) << std::endl;
for (auto element : array1)
{
std::cout << element << std::endl;
}
// std-style array
std::array<int,3> array2 = { 4, 5, 6 };
array2[1] = 25;
std::cout << "size: " <<array2.size() << std::endl;
for (auto element : array2)
{
std::cout << element << std::endl;
}
}
Here, array2.size() will return array size, no need of calculation like - (sizeof(array1) / sizeof(*array1)).
Array as method parameter:
Using below way you can pass std::array as string parameter :
#include <iostream>
#include <vector>
#include <array>
void PrintArray(int* values, int size)
{
std::cout << "size: " << size << std::endl;
for (int i = 0; i < size; ++i)
{
std::cout << values[i] << std::endl;
}
}
void PrintArray(const std::array<int,3> &values)
{
std::cout << "size: " << values.size() << std::endl;
for (auto& value : values)
{
std::cout << value << std::endl;
}
}
int main()
{
int array1[3] = { 1, 2, 3 };
PrintArray(array1, 3);
std::array<int,3> array2 = { 4, 5, 6 };
PrintArray(array2);
}
Array as return value
#include <iostream>
#include <vector>
#include <array>
int* CreateArray()
{
int* array = new int[3] { 1, 2, 3 };
return array;
}
std::array<int,3> CreateStdArray()
{
std::array<int,3> array = { 4, 5, 6 };
return array;
}
int main()
{
// c-style array
int* array1 = CreateArray();
int size = 3; // you have to know the size of the array
for (int i = 0; i < size; ++i)
{
std::cout << array1[i] << std::endl;
}
delete[] array1; // you have to delete the array
// std-style array
std::array<int,3> array2 = CreateStdArray();
for (auto element : array2)
{
std::cout << element << std::endl;
}
}
In this case called method should know data type and size of array before calling function, for variable length of array std::array is not useful.
Sort std::array
Using std::sort algorithm we can sort std::array elements. If any error occurred during execution will throw an out of range exception..
#include <iostream>
#include <vector>
#include <array>
#include <algorithm>
int main()
{
// c-style array
int array1[3] = {7, 5, 3};
std::sort(std::begin(array1), std::end(array1));
for (auto element : array1)
{
std::cout << element << std::endl;
}
// std-style array
std::array<int,3> array2 = { 7, 5, 3 };
std::sort(array2.begin(), array2.end());
for (auto element : array2)
{
std::cout << element << std::endl;
}
}
Multi-dimensional arrays
The std::array as well as the c-style array support multidimensions. These multidimensions are designed as arrays of nested arrays.
#include <iostream>
#include <array>
int main()
{
// c-style array
int array1[2][3] = { { 1, 2, 3 }, { 4, 5, 6} };
array1[0][1] = 10;
for (auto &row : array1)
{
for (auto &element : row)
{
std::cout << element << std::endl;
}
}
// std-style array
std::array<std::array<int,3>, 2> array2{ { { 7, 8, 9 }, { 10, 11, 12 } } };
array2[0][1] = 20;
for (auto &row : array2)
{
for (auto &element : row)
{
std::cout << element << std::endl;
}
}
}
Summary
The std::array is designed as zero-overhead wrapper for c-style arrays. Therefore, it comes with all the advantages of a c-style array and ads the additional advantages of C++ containers. I would recommend to use std::arrays except you have a rare special use case which comes with good reasons to use a c-style array.
Advantages of std::array
- Perfectly matches with the strict type system concept of c++
- Copy semantic / no pointer decay / the array doesn’t convert to a pointer unless you explicitly ask it to
- It knows its size
- Range check in debug builds
- No memory overhead beyond what it needs to hold its elements
- Same performance as a c-style array
- Direct support of use in STL algorithms
Disadvantages of std::array
- Slightly more awkward syntax for declaration of the array, especially when creating multi-dimensional arrays
No comments:
Post a Comment