Fur*_*ish 6 c++ language-lawyer stdlaunder
基本生活/8告诉我们,我们可以在一个对象的生命周期结束后,使用它所占用的存储空间来创建一个新的对象,并使用它原来的名称来引用它,除非:
\n\n\n\n
\n- 原始对象的类型不是 const 限定的,并且,如果是类类型,则不包含任何类型为 const 限定的非静态数据成员或引用类型,并且 [...]
\n
强调我的
\n但是,就在其下方,我们可以看到一条注释:
\n\n\n\n
\n- 如果不满足这些条件,则可以通过调用从表示其存储地址的指针获得指向新对象的指针
\nstd\xe2\x80\x8b::\xe2\x80\x8blaunder
这解释了的目的std::launder。我们可以有一个类类型const,并使用placement-new 来创建一个具有不同内部值的新对象。
让我惊讶的是第一句话的第一部分。它清楚地表明,如果存储是const(不一定包含const成员,但整个对象被声明为const),我们不能用它来引用一个新对象,但这可能意味着std::launder可以修复它。
但我们如何创建这样的对象呢?最简单的例子失败了:
\nconst auto x = 5;\nnew (&x) auto(10);\nRun Code Online (Sandbox Code Playgroud)\n这是因为我们不能用作const void*新放置的缓冲区。我们可以const_cast做到,但抛弃“真实”const性就是未定义的行为。我相信这里也是如此。
如果只是禁止使用const对象作为放置新缓冲区,我会理解,但如果是这样,那么第一个引用中强调的部分的目的是什么?我们能否真正利用重用const对象的存储重用于不同的对象吗?
显然,只需查看比我链接的标准部分低 2 个项目即可。Basic.life/10告诉我们:
在具有静态、线程或自动存储持续时间的 const 完整对象占用的存储中,或者在此类 const 对象在其生命周期结束之前占用的存储中创建新对象,会导致未定义的行为。
它附带了一个例子:
struct B {
B();
~B();
};
const B b;
void h() {
b.~B();
new (const_cast<B*>(&b)) const B; // undefined behavior
}
Run Code Online (Sandbox Code Playgroud)
这最终使我得出一个结论:在真正的对象占用的内存上使用placement-newconst是非法的。因此,我认为问题中提到的注释(参考第8点)是错误的 - 它应该排除有问题的情况。
| 归档时间: |
|
| 查看次数: |
399 次 |
| 最近记录: |