Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the address of a std::array guaranteed the same as its data?

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]; }
like image 349
463035818_is_not_a_number Avatar asked Oct 08 '21 19:10

463035818_is_not_a_number


People also ask

Does std :: array use the heap or the stack?

So in conclusion: yes, std::array is on the stack.

What is the difference between std :: array and array?

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.

Is std :: array trivial?

std::array does satisfy all the requirements of being a trivial, standard-layout class template. So the answer to your question is yes.

Is std :: array movable?

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.


1 Answers

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.

like image 118
Brian Bi Avatar answered Oct 19 '22 11:10

Brian Bi