对结构成员的临时绑定引用

0xd*_*00d 3 c++ lifetime language-lawyer temporary-objects coverity

我在一些代码库上尝试了 Coverity,我在一个类似于

struct Foo
{
    std::string name;
};

Foo getFoo();
//...
const auto& name = getFoo().name;
useName(name);
Run Code Online (Sandbox Code Playgroud)

这个代码有效吗?

我的直觉是它确实是无效的。但是,在搜索证明时,我遇到了[class.temporary]/6.4,这似乎表明它实际上格式良好。然而,Coverity 发出警告,Coverity 肯定是由一些比我更能解释标准的聪明人写的。

发出的具体 Coverity 警告是

取消引用返回的或超出范围的堆栈指针将在其作用域之后或函数返回之后访问堆栈上的无效位置。

在whateverSurroundingFunction() 中:指向在范围外返回或使用的局部堆栈变量的指针(CWE-562)

在随后的使用name。前面的警告是

out_of_scope:类型的临时变量Foo超出范围

和一种MRE的是这个(荣誉给@ user4581301在评论)。


SO 有一堆关于临时绑定引用的问题,但我所看到的每个问题都有略微不同的上下文,因此这里又出现了另一个问题。

son*_*yao 7

此代码格式良好。正如链接标准所说,返回的临时getFoo()变量的生命周期将扩展到引用变量的生命周期name

(强调我的)

每当引用绑定到临时对象或其子对象时,临时对象的生命周期都会延长以匹配引用的生命周期

引用直接绑定到临时对象的子对象 ,然后生命周期得到延长。其他方式,例如通过成员函数将引用绑定到返回数据成员的引用将不起作用。nameFoo

struct Foo
{
    std::string name;
    std::string& get_name() { return name; }
};

Foo getFoo();
Run Code Online (Sandbox Code Playgroud)

然后

const auto& name = getFoo().get_name();
std::cout << name << std::endl; // UB; name is dangled
Run Code Online (Sandbox Code Playgroud)

居住