for*_*818 11 c++ language-lawyer stdarray
std::array是...(引用自cppreference):
该容器是一个聚合类型,其语义与将 C 样式数组
T[N]作为其唯一非静态数据成员的结构体具有相同的语义。
这是否意味着数组的地址始终与其第一个元素的地址相同,即data()?
#include <array>
#include <iostream>
int main()
{
std::array<int,6> x{};
std::cout << &x << "\n";
std::cout << x.data();
}
Run Code Online (Sandbox Code Playgroud)
可能的输出:
0x7ffc86a62860
0x7ffc86a62860
Run Code Online (Sandbox Code Playgroud)
如果是的话,这有什么用吗?允许以下行为吗?
int* p = reinterpret_cast<int*>(&x);
for (int i=0;i<6;++i){ std::cout << p[i]; }
Run Code Online (Sandbox Code Playgroud)
Bri*_*ian 17
从技术上讲,std::array对象可能在开头有填充,在这种情况下,数据将位于比std::array对象更高的地址。仅对于标准布局类,才能保证对象本身与第一个非静态数据成员具有相同的地址。
标准中不保证std::array<T, N>是标准布局,即使T是int或类似的东西。所有合理的实现都std::array<T, N>将具有类型的单个非静态数据成员T[N],没有虚函数,最多只有一个没有虚拟基类的继承链,这意味着只要T本身是标准布局,它们就将是标准布局。另外,即使T不是标准布局,编译器也不太可能在对象的开头插入填充std::array。
因此,虽然假设一个std::array<T, N>对象与其包含的第一个对象具有相同的地址T是不可移植的,但在实践中基本上可以保证。您可以添加一个static_assert(sizeof(std::array<T, N>) == sizeof(T[N]));只是为了确保,如果有人尝试在实际情况并非如此的异国实现上构建您的代码,他们会知道它不受支持。