C++23 悬空引用编译错误

Ern*_*son 2 c++ reference c++23

以下显然会导致 C++23 中的编译错误:

int& f(int& x) {
    int y = ++x;
    return y;
}
Run Code Online (Sandbox Code Playgroud)

错误cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'

但这似乎没有给我们一个警告:

int& f(int x) {
    int &y = ++x;
    return y;
}
Run Code Online (Sandbox Code Playgroud)

这在编译阶段是不是更难捕捉?

谢谢。

Jan*_*tke 6

为什么第一个示例无法编译,与第二个示例不同

要理解其中的差异,必须理解为什么代码无法在 C++23 中编译。即,在第一个示例中,y可移动的,因为它命名了一个隐式可移动实体并出现在return语句中。所以:

如果表达式符合移动条件,则它是 xvalue(见下文);如果实体是函数、变量,则为左值 [...]

- [expr.prim.id.unqual] p1

隐式可移动实体是具有自动存储持续时间的变量,它可以是非易失性对象,也可以是对非易失性对象类型的右值引用。

- [expr.prim.id.unqual] p4

在第一个示例中, 的移动资格y使其成为右值,并且返回的引用无法绑定到它。在第二个示例中,y未命名隐式可移动实体,因此将其视为左值,并且引用绑定成功。

第一个示例无法编译的事实并不是因为C++ 委员会已努力检测悬空引用;而是因为 C++ 委员会已尽力检测悬空引用。相反,这只是当涉及到return语句中的隐式移动时,某些措辞更改的一个方便的副作用。

一般检测悬空引用

检测这种微不足道的情况之外的悬空引用是非常困难的。它通常需要函数的生命周期注释,类似于 Rust。一些提案至少专注于检测简单的案例。

例如,Herb Sutter 在P1179:Lifetime safety: Preventing common dangling中提出了基于非循环控制流图(ACFG)的标准化分析。这至少使得本地分析(在同一功能内)成为可能。该提案长达 47 页,这一事实表明这不是一个小问题。

更多琐碎的情况可以通过@BrianBi的提案P2748来捕获:禁止将返回的左值绑定到临时值

  • @WeijunZhou据我所知[P2255:检测引用绑定到临时的类型特征](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2255r2.html)可以仅检测引用何时绑定到临时对象,而不检测何时绑定到当前函数本地且在函数返回时悬空的对象。这可能有助于消除一些进一步的琐碎案例。 (2认同)