【问题标题】:Temporary bound references to struct members对结构成员的临时绑定引用
【发布时间】:2020-08-27 19:32:07
【问题描述】:

我在一些代码库上尝试使用 Coverity,但在类似于

的代码上收到警告
struct Foo
{
    std::string name;
};

Foo getFoo();
//...
const auto& name = getFoo().name;
useName(name);

此代码有效吗?

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

发出的具体 Coverity 警告是

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

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

关于name 的后续用法。前面的警告是

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

一种 MRE 是 this(感谢 cmets 中的 @user4581301)。


SO 有很多关于临时绑定引用的问题,但我看到的每个问题的上下文都略有不同,因此这里还有一个关于它们的问题。

【问题讨论】:

  • 是的,引用会延长临时对象的生命周期。但这不适用于这里,因为您没有创建对临时值的引用。真的不是。它是对临时对象是其实例的类成员的引用。大不同。
  • 但是,我链接的段落 (/6.4) 没有涵盖它吗?如果不是,我应该如何阅读它——也就是说,/6.4 涵盖了哪些内容?
  • 我建议使用合法的 MCVE 来强化您的问题,例如 godbolt.org/z/S9NXsT 。我想看看语言律师通过后如何解决。
  • @user4581301 您的示例已经足够接近(我认为),如果您不介意,我会将其链接到问题正文中。
  • Coverity 是否对 Godbolt 示例发出警告?

标签: c++ language-lawyer lifetime coverity temporary-objects


【解决方案1】:

这段代码格式正确。正如链接标准所说,getFoo() 返回的lifetime of the temporary 将延长到引用变量name 的生命周期。

(强调我的)

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

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

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

Foo getFoo();

然后

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

LIVE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    相关资源
    最近更新 更多