考虑这段代码:
struct Block {
alignas(int) unsigned char data[sizeof(int)];
};
int main() {
Block buff[sizeof(double) / sizeof(int)];
::new(&buff) double();
double d = *std::launder(reinterpret_cast<double*>(&buff));
return 0;
}
这个用法正确吗?
reinterpret_cast
是否会导致未定义的行为?
它具有定义的行为,假设
double
没有比int
更强的对齐要求,并且sizeof(double)
是sizeof(int)
的整数倍。
但是,如果
sizeof(double) > sizeof(int)
,那么就没有 unsigned char
数组可以为 double
对象提供存储,因此 ::new(&buff) double()
将结束 buff
对象(及其所有子对象)的生命周期。 double
对象不会嵌套在 buff
中,而是重用其存储。
在这种情况下,只要析构函数很简单,无论您使用
Block
类型还是任何其他类型的合适对齐和大小都没有关系。如果析构函数非常重要,那么在 Block
的存储中没有透明地替换原始对象的 buff
(数组)对象处于活动状态时,作用域末尾的隐式析构函数调用将导致未定义的行为。