Basic.life/8告诉我们,我们可以使用对象占用的存储空间在其生命周期结束后创建一个新对象,并使用其原始名称来引用它,除非:
- 原始对象的类型不是 const 限定的,如果是类类型,则不包含任何类型为 const 限定或引用类型的非静态数据成员,并且 [...]
强调我的
但是,就在下面,我们可以看到一条注释说:
- 如果不满足这些条件,则可以从表示其存储地址的指针中获取指向新对象的指针,方法是调用
std::launder
这解释了std::launder
. 我们可以有一个具有const
成员的类类型,并使用placement-new 在其中创建一个具有不同内部值的新对象。
令我惊讶的是第一句话的第一部分。它清楚地表明,如果存储是const
(不一定包含const
成员,但整个对象被声明为const
),我们不能使用它来按原样引用新对象,但它可能暗示std::launder
可以修复它。
但是我们如何创建这样的对象呢?最简单的例子失败了:
const auto x = 5;
new (&x) auto(10);
这是因为我们不能const void*
用作placement-new 的缓冲区。我们可以const_cast
做到,但抛弃“真实”const
是未定义的行为。我相信这里也是如此。
我会理解是否只是禁止使用const
对象作为放置新缓冲区,但如果是这样的话,第一个引号的强调部分的目的是什么?我们可以为不同的对象重用一个真正const
对象的存储吗?