Sec*_*ndi 15 c++ language-lawyer c++17 c++20
从 C++20 开始,对象生存期的约束发生了重大变化,从basic.life#8.3到 n4861/basic.life#8.3。我想在这里重点关注的具体变化是(C++20 草案)
如果一个对象的生命周期结束后,在该对象占用的存储空间被重用或释放之前,在原对象占用的存储位置上创建一个新的对象,一个指向原对象的指针,一个指向该对象的引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,如果原始对象是透明可替换的(请参阅如下)由新对象。对象 o1 可以透明地被对象 o2 替换,如果
- o2 占用的存储空间正好覆盖 o1 占用的存储空间,并且
- o1 和 o2 属于同一类型(忽略顶级 cv 限定符),并且
- o1 不是一个完整的 const 对象,并且
- o1 和 o2 都不是潜在重叠的子对象,并且
- 或者o1和o2都是完整的对象,或者o1和o2分别是对象p1和p2的直接子对象,并且p1可以透明地被p2替换。
与 C++20 之前的版本相比(不是唯一的变化,请参阅草稿了解详细信息)
- 原始对象的类型不是 const 限定的,并且如果是类类型,则不包含任何类型为 const 限定的非静态数据成员或引用类型...
问题 1:也许太明显了,只是为了确定:对于complete const object,标准指的是 const 的完整对象,对吧?(所以它与部分/完整 const 对象无关,这是本节中先前措辞质量的一部分?)
问题 2:谁能解释一下这些变化(别名?)背后的原因吗?
问题 3:我的假设是否有效,即这是对以前规则的大幅放松,即保证现在更多的对象/内存重用场景不会成为 UB?有疑问,它们是否应该影响优化器以繁重的方式运行的方式(效率字段的转变)?
问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做了constexpr(P1004R2),由于核心语言UB需要在不断的评估中进行诊断而导致失败(N4868 [expr.const]/5.7),因此缺陷变得明显。
| 归档时间: |
|
| 查看次数: |
496 次 |
| 最近记录: |