Reputation: 2877
Pardon my ignorance, it appears to me that std::array
is meant to be an STL replacement for your regular arrays. But because the array size has to be passed as a template parameter, it prevents us from creating std::array
with a size known only at runtime.
std::array<char,3> nums {1,2,3}; // Works.
constexpr size_t size = 3;
std::array<char,size> nums {1,2,3}; // Works.
const buf_size = GetSize();
std::array<char, buf_size> nums; // Doesn't work.
I would assume that one very important use case for an array in C++ is to create a fixed size data structure based on runtime inputs (say allocating buffer for reading files).
The workarounds I use for this are:
// Create a array pointer for on-the-spot usecases like reading from a file.
char *data = new char[size];
...
delete[] data;
or:
// Use unique_ptr as a class member and I don't want to manage the memory myself.
std::unique_ptr<char[]> myarr_ = std::unique_ptr<char[]>(new char[size]);
If I don't care about fixed size, I am aware that I can use std::vector<char>
with the size pre-defined as follows:
std::vector<char> my_buf (buf_size);
Why did the designers of std::array
choose to ignore this use case? Perhaps I don't understand the real usecase for std::array
.
EDIT: I guess another way to phrase my question could also be - Why did the designers choose to have the size passed as a template param and not as a constructor param? Would opting for the latter have made it difficult to provide the functionality that std::array
currently has? To me it seems like a deliberate design choice and I don't understand why.
Upvotes: 7
Views: 3020
Reputation: 155075
The two main reasons I understand are:
std::array
implements STL's interfaces for collection-types, allowing an std::array
to be passed as-is to functions and methods that accept any STL iterator....this is the preservation of type information across function/method boundaries because it prevents Array Pointer Decay.
Given a naked C/C++ array, you can pass it to another function as a parameter argument by 4 ways:
void by_value1 ( const T* array )
void by_value2 ( const T array[] )
void by_pointer ( const T (*array)[U] )
void by_reference( const T (&array)[U] )
by_value1
and by_value2
are both semantically identical and cause pointer decay because the receiving function does not know the sizeof
the array.by_pointer
and by_reference
both requires that U
by a known compile-time constant, but preserve sizeof
information.So if you avoid array decay by using by_pointer
or by_reference
you now have a maintenance problem every time you change the size of the array you have to manually update all of the call-sites that have that size in U
.
By using std::array
it's taken care of for you by making those functions template
functions where U
is a parameter (granted, you could still use the by_pointer
and by_reference
techniques but with messier syntax).
...so std::array
adds a 5th way:
template<typename T, size_t N>
void by_stdarray( const std::array<T,N>& array )
Upvotes: 4
Reputation: 69988
std::array
facilitates several beneficial interfaces and idioms which are used in std::vector
. With normal C-style arrays, one cannot have .size()
(no sizeof
hack), .at()
(exception for out of range), front()/back()
, iterators, so on. Everything has to be hand-coded.
Many programmers may choose std::vector
even for compile time known sized arrays, just because they want to utilize above programming methodologies. But that snatches away the performance available with compile time fixed size arrays.
Hence std::array
was provided by the library makers to discourage the C-style arrays, and yet avoid std::vector
s when the size is known at the compile time.
Upvotes: 9
Reputation: 6125
std::array
is a replacement for C-style arrays.
The C++ standards don't allow C-style arrays to be declared without compile-time defined sizes.
Upvotes: 0