考虑这段代码:
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
另外,标准不能保证 后不会填充
data
,因此计算可能不会按照您期望的方式运行,尽管它不会影响我上面写的内容。还只能保证data
类中成员的偏移量为零,因为该类是标准布局的。