C++ 单线。在同一行上构造对象和调用函数是否合法

A4A*_*ril 4 c++

此代码似乎在启用优化的广泛使用的编译器上中断,尽管它在 Visual Studio 中运行良好。

struct foo
{
    foo(int a) { s[0] = '0'+a%10;s[1] = '\0'; }
    const char * bar() const { return &s[0]; }
    char s[4];
};

int main( )
{
    const char * s = foo(1234).bar();
    printf("%p %s\n", s, s);
}
Run Code Online (Sandbox Code Playgroud)

我希望即使 foo 是一个右值,它也会在堆栈上构造,并且 's' 将指向有效数据。但是,对于 GCC(版本 7.5 和 9),缓冲区永远不会被初始化。

编译失败示例:

g++-9 --std=c++11 -Wall -pedantic -O3 -o example example.cpp
Run Code Online (Sandbox Code Playgroud)

cig*_*ien 7

在这一行:

const char * s = foo(1234).bar();
Run Code Online (Sandbox Code Playgroud)

s指向char s[4]一个临时foo对象的成员。在完整表达式的末尾,该对象死亡,s现在指向无效内存。在下一行打印它会调用未定义的行为。


这里的问题是使用bar(). 链式函数调用本身很好,所以如果你直接在printf它的定义良好的表达式中使用:

printf("%s\n", foo(1234).bar());  // ok
Run Code Online (Sandbox Code Playgroud)

  • @HikmatFarhat 是的,这仍然是 UB,引用仅延长它们引用的对象的生命周期,而不是临时内部缓冲区的函数返回指针。即 `auto && f = foo(); const char *s = f.bar();` 更好 (5认同)