C++20 中对象的隐式创建,理解提案的类型双关示例

2023-12-13

我试图完全理解 C++20 的一个新功能:对象的隐式创建。

中有这个例子proposal,“3.3 类型双关”一节:

我们不希望以下示例成为有效的:

float do_bad_things(int n) {
    alignof(int) alignof(float) char buffer[max(sizeof(int), sizeof(float))];
    *(int*)buffer = n;                      // #1
    new (buffer) std::byte[sizeof(buffer)]; // #X
    return (*float*)buffer;                 // #2
}

提议的规则将允许 int 对象出现以使第 #1 行有效(在每种情况下),并且将允许 float 对象同样出现以使第 #2 行有效。

为什么(由我)标记为#X 的行是必要的?这有什么不同吗?如果没有这一行,这个例子不是完全相同吗?

我的推理是:buffer是一个 char 数组,因此它隐式创建对象。所以,在第 1 行,int是隐式创建的。同样,在第 #2 行,afloat即使没有 #X 行,也会被隐式创建(因为buffer已经具有隐式创建对象属性)。所以看起来#X 行没有添加任何内容。我错了吗?


为什么(由我)标记为#X 的行是必要的?

因为这会调用隐式对象创建。

C++20 中的隐式对象创建 (IOC) 不是chaos。它并不是“每个对象每次都存在于每个可能的内存位置”。相反,它是一种量子状态:当在一块内存上调用 IOC 规则时,会创建一个对象。你只是不知道它是什么。当您实际将内存用于特定对象时,事实证明,这是在内存上调用 IOC 时创建的对象(或与其兼容的对象)。

如果你对存储做了任何事情使得单个对象无法同时满足这两个要求,那么你就会得到 UB。

一段记忆无法容纳一个int and a float在他们一生的同一时间里。国际奥委会并没有改变这一点。

第 1 行使用 IOC 创建一个int在存储中;到那时,它在功能上与int buffer;。第 2 行尝试访问float在该存储中,但不存在这样的对象。如果有一个int已经存在了,国际奥委会无法创建一个float在它的上面。

第 X 行通过重用存储来结束该内存中所有对象的生命周期;没有int不再有。由于正在创建的对象是bytearray,这也为IOC的存储重新加持。这就是 2 号线运行的原因。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++20 中对象的隐式创建,理解提案的类型双关示例 的相关文章

随机推荐