是否可以根据 C++20 中稍后的运行时决定存在不同的隐式对象?

M.M*_*M.M 11 c++ language-lawyer c++20

这个问题是指在最新的C++20草案中增加了P0593

这是我的例子:

#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]
}
Run Code Online (Sandbox Code Playgroud)

此代码是否针对最新草案下的所有输入进行了明确定义?

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

对于程序的任何实际运行,都存在一个未指定的隐式对象集的成员,可以使程序定义良好。但是我不清楚 [intro.object]/10 中提到的隐式对象创建的选择是否必须在malloc发生时进行;或者决定是否可以“时间旅行”。

对于将二进制 blob 读入缓冲区然后做出如何访问它的运行时决定(例如反序列化;并且标头告诉我们是浮点数还是整数即将出现)的程序,可能会出现同样的问题。

Nic*_*las 8

隐式对象创建应该只发生一次,在malloc; 它不是由foo.

那不相关。重要的是创建了哪个对象。该标准说,被创建的对象是一个将本来应该是 UB 的东西变成定义良好的代码的对象:

该操作在其指定的存储区域中隐式地创建和启动零个或多个隐式生命周期类型([basic.types])对象的生命周期,如果这样做会导致程序具有定义的行为。

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

因此,创建的位置始终是“操作”,但确定创建的内容是基于运行时如何使用内存(即:行为)。

  • 明确地说,你是说我的代码定义良好? (2认同)