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

C++ 在C+中隐式创建对象+;20、理解提案的类型双关示例,c++,c++20,C++,C++20,我试图完全理解C++20的一个新特性,隐式创建对象 “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

我试图完全理解C++20的一个新特性,隐式创建对象

“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
是一个字符数组,因此它隐式地创建对象。因此,在第1行,隐式创建了一个
int
。同样,在第#2行,即使没有第#X行,
float
也会隐式创建(因为
buffer
已经具有隐式创建对象属性)。因此,第#X行似乎没有添加任何内容。我错了吗

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

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

C++20中的隐式对象创建(IOC)并不混乱。它不是“每个对象在任何时候都存在于每个可能的内存位置”,而是一种量子状态:当对一块内存调用IOC规则时,会创建一个对象。你只是不知道那是什么。当您实际为特定对象使用内存时,结果表明这是在内存上调用IOC时创建的对象(或与之兼容的对象)

如果您对存储做了任何操作,使得单个对象不能同时满足这两个要求,那么您将得到UB

一块内存不能在其生命周期内同时保存
int
float
。国际奥委会不会改变这一点

第1行使用IOC在存储器中创建
int
;在这一点上,它在功能上与
int buffer没有什么不同。第2行尝试访问该存储中的
浮点
,但不存在这样的对象。如果已经有一个
int
,IOC就不能在它上面创建一个
浮点


第X行通过重用存储器来结束该内存中所有对象的生存期;不再有
int
了。由于创建的对象是一个
字节
数组,因此这也为IOC的存储提供了便利。这就是第2行工作的原因。

那么这个功能是否像oracle一样工作?在
字符缓冲区[…]
,我们不知道缓冲区将用于什么。尽管如此,该行还是会创建一个
int
对象,因为程序将来会将其用作
int
?我问这个问题,因为你说第1行创建了
int
对象,这与我目前的理解相矛盾。创建发生在哪里?该提案称“创建一个字符、无符号字符或std::byte数组会隐式地在该数组中创建对象”。因此,似乎创建发生在
字符缓冲区[…]
,而不是第1行。当然,这种差异可能无法观察到,但可能有助于我如何看待这一功能。@geza:“那么这一功能的工作方式是否像甲骨文?”。我喜欢把它想象成一个量子态。它总是有正确的目标;你只是还不知道而已。是的,实际的创建发生在“隐式创建对象”点,而不是您使用它的地方。这就是为什么我喜欢把它看作一个量子态。