std::array 的地址是否保证与其数据相同?
Is the address of a std::array guaranteed the same as its data?
std::array
是...(引用自 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.
这是否意味着数组的地址总是与其第一个元素的地址相同,即 data()
?
#include <array>
#include <iostream>
int main()
{
std::array<int,6> x{};
std::cout << &x << "\n";
std::cout << x.data();
}
可能的输出:
0x7ffc86a62860
0x7ffc86a62860
如果是,这有什么用吗?是否允许以下内容?
int* p = reinterpret_cast<int*>(&x);
for (int i=0;i<6;++i){ std::cout << p[i]; }
从技术上讲,std::array
对象的开头可能有填充,在这种情况下,数据将位于比 std::array
对象更高的地址。只有 standard-layout 类 才能保证对象本身具有与第一个非静态数据成员相同的地址。
标准中不能保证 std::array<T, N>
是标准布局,即使 T
是 int
或类似的布局。 std::array<T, N>
的所有 合理 实现都将有一个 T[N]
类型的非静态数据成员,没有虚函数,并且最多只有一个没有虚函数的继承链base 类,这意味着只要 T
本身是标准布局,它们就会是标准布局。另外,即使 T
不是标准布局,编译器也不太可能在 std::array
对象的开头插入填充。
所以,虽然假设一个std::array<T, N>
对象与其包含的第一个T
对象具有相同的地址是不可移植的,但在实践中基本可以保证。您可以添加 static_assert(sizeof(std::array<T, N>) == sizeof(T[N]));
只是为了确保,如果有人试图在并非如此的奇异实现上构建您的代码,他们就会知道它不受支持。
std::array
是...(引用自 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.
这是否意味着数组的地址总是与其第一个元素的地址相同,即 data()
?
#include <array>
#include <iostream>
int main()
{
std::array<int,6> x{};
std::cout << &x << "\n";
std::cout << x.data();
}
可能的输出:
0x7ffc86a62860
0x7ffc86a62860
如果是,这有什么用吗?是否允许以下内容?
int* p = reinterpret_cast<int*>(&x);
for (int i=0;i<6;++i){ std::cout << p[i]; }
从技术上讲,std::array
对象的开头可能有填充,在这种情况下,数据将位于比 std::array
对象更高的地址。只有 standard-layout 类 才能保证对象本身具有与第一个非静态数据成员相同的地址。
标准中不能保证 std::array<T, N>
是标准布局,即使 T
是 int
或类似的布局。 std::array<T, N>
的所有 合理 实现都将有一个 T[N]
类型的非静态数据成员,没有虚函数,并且最多只有一个没有虚函数的继承链base 类,这意味着只要 T
本身是标准布局,它们就会是标准布局。另外,即使 T
不是标准布局,编译器也不太可能在 std::array
对象的开头插入填充。
所以,虽然假设一个std::array<T, N>
对象与其包含的第一个T
对象具有相同的地址是不可移植的,但在实践中基本可以保证。您可以添加 static_assert(sizeof(std::array<T, N>) == sizeof(T[N]));
只是为了确保,如果有人试图在并非如此的奇异实现上构建您的代码,他们就会知道它不受支持。