基于C ++ 20中更高版本的运行时决策,可以存在不同的隐式对象吗?


11

这个问题是指在最新的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]
}

对于最新草案下的所有输入,此代码是否定义明确?

P0593中表达的基本原理非常清楚地表明[2],如果两个用户输入项不同,则由于严格的混叠冲突,取消注释将导致未定义的行为。隐式对象的创建应该只发生一次malloc;它不是由中的赋值语句触发的foo

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

对于将二进制Blob读入缓冲区,然后做出如何访问它的运行时决策的程序,可能会出现相同的问题(例如,反序列化;并且标头会告诉我们是否出现了float或int)。

Answers:


9

隐式对象的创建应该只发生一次malloc;它不是由中的赋值语句触发的foo

没关系 重要的是创建哪个对象。该标准说,要创建的对象是将UB变成定义良好的代码的对象:

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

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

因此,创建的位置始终是“操作”,但是要确定要创建的内容取决于运行时内存的使用方式(即行为)。


2
明确地说,您是说我的代码定义明确?
MM

2
@MM:是的。
Nicol Bolas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.