返回传入的临时值并在同一语句中读取它是否安全?

spr*_*aff 9 c++ scope undefined-behavior

我只是写了这篇文章而没有想太多.它似乎工作正常,但我不确定它是否严格安全.

class Foo
{
    struct Buffer
    {
        char data [sizeof ("output will look like this XXXX YYYY ZZZZ")];
    };

    const char * print (const char * format = DEFUALT_FORMAT, Buffer && buf = Buffer ())
    {
        sort_of_sprintf_thing (format, buf .data, sizeof (buf.data), ...);
        return buf .data;
    }
};

std :: cout << Foo () .print ();
Run Code Online (Sandbox Code Playgroud)

所以我认为语义是临时缓冲区将保持存在直到整个cout语句完成.这是对的,还是会在此之前超出范围,在这种情况下,这是UB?

eca*_*mur 6

是的,您的代码定义明确.

[class.temporary]

3 - [...]作为评估全表达式(1.9)的最后一步,(词法上)包含创建它们的点,临时对象被销毁.[...]

[intro.execution]

11 - [注意:对完整表达式的评估可以包括对词汇表的评估,这些子表达式不是词法表达式的全部表达式.例如,计算默认参数(8.3.6)所涉及的子表达式被认为是在调用函数的表达式中创建的,而不是在定义默认参数的表达式中创建的. - 结束说明]

但这并不意味着它特别 - 将结果绑定Foo().print()char const*变量上太容易了,这会使下一个完整表达式成为悬空指针.

  • @Aggieboy:这就是为什么这是一个代码气味,你进入的设计充其量只是*脆弱*(我认为它破碎了,但我愿意接受*脆弱的*作为中间地带).如果你想重载,成本不是那么大,你需要一个用户提供缓冲区的重载,而另一个不提供缓冲区,你需要确保为用户提供一个释放资源的机制.第二次重载......两次重载本质上是非常不同的. (2认同)

Dav*_*eas 5

代码很糟糕,问题不在于调用站点,而是在print函数上.你正在使用一个rvalue(只有绑定到rvalue-reference的东西)并返回一个指向其内部的指针,这是一个未定义行为的配方(如果用户取消引用const char*返回的).

在您拥有的特定示例中,Foo()临时将足够长,但是此代码很容易让客户端存储const char*超出完整表达式并导致未定义的行为.