根据 C++20 中稍后的运行时决策,是否可以有不同的隐式 objects?

Can there be different implicit objects based on a later runtime decision in C++20?

这道题是指P0593 to the latest C++20 draft的加法。

这是我的例子:

#include <cstdlib>
#include <cstdio>

void foo(void *p)
{
    if ( std::getchar() == 'i' )
    {
        *(int *)p = 2;
        std::printf("%d\n", *(int *)p);
    }
    else
    {
        *(float *)p = 2;
        std::printf("%f\n", *(float *)p);
    }
}

int main()
{
    void *a = std::malloc( sizeof(int) + sizeof(float) );
    if ( !a ) return EXIT_FAILURE;

    foo(a);
    // foo(a);    [2]
}

这个代码well-defined是否适用于最新草案下的所有输入?

P0593 中表达的基本原理非常清楚,如果两个用户输入项不同,取消注释 [2] 将导致由于严格的别名违规而导致未定义的行为。隐式 object 创建应该只发生一次,在 malloc 点;它不是由 foo.

中的赋值语句触发的

对于程序的任何实际 运行,存在一个未指定的隐式 object 集合的成员,它会使程序 well-defined。但是我不清楚 [intro.object]/10 中提到的隐式 object 创建的选择是否必须在 malloc 发生时进行;或者决定是否可以 "time travel" .

将二进制 blob 读入缓冲区然后运行时间决定如何访问它的程序可能会出现同样的问题(例如反序列化;header 告诉我们无论是 float 还是 int 即将出现)。

The implicit object creation is supposed to happen just once, at the point of malloc; it isn't triggered by the assignment statement in foo.

这不相关。重要的是创建了哪个对象。该标准表示,创建的对象是将 UB 变成定义明确的代码的对象:

that operation implicitly creates and starts the lifetime of zero or more objects of implicit-lifetime types ([basic.types]) in its specified region of storage if doing so would result in the program having defined behavior.

行为最终基于运行时间执行,而不是静态分析。因此,您只需要跟踪程序的执行,直到您 运行 进入一种情况,在这种情况下,行为不会被定义,但如果在操作时在该存储中创建了某种类型的对象,则会被定义问题。

所以创建的位置总是"the operation",但是创建什么的决定是基于内存在运行时间的使用方式(即:行为)。