我刚刚阅读了std::launder的用途是什么?
老实说,我现在有点摸不着头脑。
让我们从@NicolBolas的回答中第二个示例开始:
aligned_storage<sizeof(int), alignof(int)>::type data; new(&data) int; int *p = std::launder(reinterpret_cast<int*>(&data));
[basic.life]/8告诉我们,如果您在旧对象的存储中分配一个新对象,则无法通过指向旧对象的指针访问新对象。
std::launder
可以帮助我们避开这个问题。那么,为什么不直接更改语言标准,使通过
reinterpret_cast<int *>(&data)
访问data
是有效/适当的呢?在现实生活中,洗钱是一种隐藏事实的方式以躲避法律。但我们没有任何需要隐藏的东西-我们在这里做的是完全合法的事情。那么,当编译器注意到我们以这种方式访问data
时,为什么不能将其行为更改为其std::launder()
行为?接下来是第一个示例:
X *p = new (&u.x) X {2};
因为X是微不足道的,所以我们在创建一个新对象来替换旧对象之前无需销毁旧对象,因此这是完全合法的代码。新对象将具有n成员2。
那么告诉我...
u.x.n
会返回什么?显而易见的答案将是2。但是这是错误的,因为编译器可以假定一个真正的const变量(不仅仅是一个const&,而是声明为const的对象变量)永远不会改变。但我们刚刚改变了它。
那么,为什么不让编译器在我们通过指针访问常量字段时,不允许做出这种假设呢?
为什么要有这种伪函数来打破正式语言语义,而不是根据代码是否像这些示例一样执行某些操作来设置语义?
launder
在一个非常小的范围内禁用了优化。 - dypu.x.n
不会改变是完全合理的。 - Nicol Bolas