std::array 的地址是否保证与其数据相同?

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>是标准布局,即使Tint或类似的东西。所有合理的实现都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]));只是为了确保,如果有人尝试在实际情况并非如此的异国实现上构建您的代码,他们会知道它不受支持。

  • @NateEldredge 该特定实现不符合要求。各种垃圾成员会干扰聚合初始化。 (4认同)
  • @RemyLebeau 聚合和标准布局是不同的东西。您可以拥有非标准布局聚合。 (2认同)