以下显然会导致 C++23 中的编译错误:
int& f(int& x) {
int y = ++x;
return y;
}
错误:
cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
但是这个one似乎甚至没有给我们警告:
int& f(int x) {
int &y = ++x;
return y;
}
这在编译阶段很难捕获吗?
谢谢。
要理解其中的差异,必须理解为什么代码无法在 C++23 中编译。 也就是说,在第一个示例中,
y
是 move-eligible,因为它命名了一个 隐式可移动实体 并出现在 return
语句中。因此:
如果表达式符合移动条件,则它是一个x值(见下文);如果实体是函数、变量,则为左值 [...]
在第二个示例中,
y
没有命名隐式可移动实体,因此它被认为是左值,并且引用绑定成功。
第一个示例无法编译的事实不是,因为 C++ 委员会已努力检测悬空引用;相反,这只是当涉及到
return
语句中的隐式移动时,一些措辞更改的一个方便的副作用。
检测除此之外的悬空引用,微不足道的情况是非常困难的。它通常需要函数的生命周期注释,类似于 Rust。 有些提案至少专注于检测简单的案例。
例如,Herb Sutter 在P1179:终身安全:防止常见悬空中提出了基于非循环控制流图(ACFG)的标准化分析。这至少使得本地分析(在同一功能内)成为可能。该提案长达 47 页,这一事实表明这不是一个小问题。