C++20 中对象生命周期约束更改的说明和原因

Sec*_*ndi 15 c++ language-lawyer c++17 c++20

从 C++20 开始,对象生存期的约束发生了重大变化,从basic.life#8.3n4861/basic.life#8.3。我想在这里重点关注的具体变化是(C++20 草案)

如果一个对象的生命周期结束后,在该对象占用的存储空间被重用或释放之前,在原对象占用的存储位置上创建一个新的对象,一个指向原对象的指针,一个指向该对象的引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,如果原始对象是透明可替换的(请参阅如下)由新对象。对象 o1 可以透明地被对象 o2 替换,如果

  1. o2 占用的存储空间正好覆盖 o1 占用的存储空间,并且
  2. o1 和 o2 属于同一类型(忽略顶级 cv 限定符),并且
  3. o1 不是一个完整的 const 对象,并且
  4. o1 和 o2 都不是潜在重叠的子对象,并且
  5. 或者o1和o2都是完整的对象,或者o1和o2分别是对象p1和p2的直接子对象,并且p1可以透明地被p2替换。

与 C++20 之前的版本相比(不是唯一的变化,请参阅草稿了解详细信息)

  1. 原始对象的类型不是 const 限定的,并且如果是类类型,则不包含任何类型为 const 限定的非静态数据成员或引用类型...

问题 1:也许太明显了,只是为了确定:对于complete const object,标准指的是 const 的完整对象,对吧?(所以它与部分/完整 const 对象无关,这是本节中先前措辞质量的一部分?)

问题 2:谁能解释一下这些变化(别名?)背后的原因吗?

问题 3:我的假设是否有效,即这是对以前规则的大幅放松,即保证现在更多的对象/内存重用场景不会成为 UB?有疑问,它们是否应该影响优化器以繁重的方式运行的方式(效率字段的转变)?

F.v*_*.S. 3

问1:是的。const此外,在确定哪个对象是“完整 const 对象”时,成员是否是无关的。例如

struct HasConstMem { const int n = 42; };
HasConstMem       foo;  // not a complete const object
const HasConstMem bar;  // a complete const object

auto px = new HasConstMem;       // points to a complete non-const object
auto py = new const HasConstMem; // points to a complete const object
Run Code Online (Sandbox Code Playgroud)

Q2:IMO,旧规范不允许std::vector<HasConstMem>在没有 的情况下工作std::launder,这是有缺陷的。

std::vectorQ3:理论上有一些技术是优化器不允许的,但这些技术不应该存在,否则之前的行为已经被证明是损坏的。在C++20中,std::vector做了constexprP1004R2),由于核心语言UB需要在不断的评估中进行诊断而导致失败(N4868 [expr.const]/5.7),因此缺陷变得明显。