这取决于封闭数组对象是否是一个完整的对象,如果不是,您是否可以通过指向该封闭数组对象的指针有效地访问更多字节(例如,因为它本身是一个数组元素,或者可以与更大的对象进行指针互转换) ,或与数组元素的对象进行指针互换)。 “可达”要求意味着您不能使用launder
获取一个指针,该指针允许您访问比源指针值允许的更多字节,但存在未定义的行为。这确保了某些未知代码可能调用的可能性launder
不影响编译器的转义分析。
我想一些例子会有所帮助。下面每个例子reinterpret_cast
s a int*
指向 10 数组的第一个元素int
变成一个int(*)[10]
。由于它们不可进行指针互换,reinterpret_cast
不改变指针值,你会得到一个int(*)[10]
值为“指向第一个元素(无论数组是什么)的指针”。然后,每个示例尝试通过调用来获取指向整个数组的指针std::launder
在强制转换指针上。
int x[10];
auto p = std::launder(reinterpret_cast<int(*)[10]>(&x[0]));
还行吧;您可以访问的所有元素x
通过源指针,以及结果launder
不允许您访问任何其他内容。
int x2[2][10];
auto p2 = std::launder(reinterpret_cast<int(*)[10]>(&x2[0][0]));
这是未定义的。您只能访问以下元素x2[0]
通过源指针,但结果(这将是一个指向x2[0]
)将允许您访问 x2[1],但您无法通过源访问。
struct X { int a[10]; } x3, x4[2]; // assume no padding
auto p3 = std::launder(reinterpret_cast<int(*)[10]>(&x3.a[0])); // OK
还行吧。同样,您不能通过指针访问x3.a
您还无法访问的任何字节。
auto p4 = std::launder(reinterpret_cast<int(*)[10]>(&x4[0].a[0]));
这是(打算)未定义的。你本来可以到达x4[1]
从结果来看,因为x4[0].a
是指针可相互转换的x4[0]
,所以指向前者的指针可以是reinterpret_cast
产生指向后者的指针,然后可以将其用于指针算术。看https://wg21.link/LWG2859 https://wg21.link/LWG2859.
struct Y { int a[10]; double y; } x5;
auto p3 = std::launder(reinterpret_cast<int(*)[10]>(&x5.a[0]));
这又是未定义的,因为你本来可以达到x5.y
从结果指针(通过reinterpret_cast
to a Y*
)但源指针不能用于访问它。