std::array
is ... (quoting from cppreference):
This container is an aggregate type with the same semantics as a struct holding a C-style array
T[N]
as its only non-static data member.
Does that imply that the address of an array is always the same as the address of its first element, i.e. data()
?
#include <array>
#include <iostream>
int main()
{
std::array<int,6> x{};
std::cout << &x << "\n";
std::cout << x.data();
}
Possible output:
0x7ffc86a62860
0x7ffc86a62860
And if yes, is this of any use? Is the following allowed?
int* p = reinterpret_cast<int*>(&x);
for (int i=0;i<6;++i){ std::cout << p[i]; }
So in conclusion: yes, std::array is on the stack.
std::array is just a class version of the classic C array. That means its size is fixed at compile time and it will be allocated as a single chunk (e.g. taking space on the stack). The advantage it has is slightly better performance because there is no indirection between the object and the arrayed data.
std::array does satisfy all the requirements of being a trivial, standard-layout class template. So the answer to your question is yes.
std::array is movable only if its contained objects are movable. std::array is quite different from the other containers because the container object contains the storage, not just pointers into the heap. Moving a std::vector only copies some pointers, and the contained objects are none the wiser.
Technically, a std::array
object may have padding at the beginning, in which case the data will be at a higher address than the std::array
object. Only for standard-layout classes is there a guarantee that the object itself has the same address as the first non-static data member.
There is no guarantee in the standard that std::array<T, N>
is standard-layout, even if T
is int
or something like that. All reasonable implementations of std::array<T, N>
will have a single non-static data member of type T[N]
, no virtual functions, and at most a single inheritance chain with no virtual base classes, which would mean they would be standard-layout as long as T
itself is standard-layout. Plus, even if T
is not standard-layout, the compiler is not likely to insert padding at the beginning of the std::array
object.
So, while an assumption that a std::array<T, N>
object has the same address as the first T
object it contains is not portable, it is basically guaranteed in practice. And you can add a static_assert(sizeof(std::array<T, N>) == sizeof(T[N]));
just to be sure that, if someone ever tries to build your code on an exotic implementation where it isn't the case, they'll know it's not supported.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With