返回的局部变量引用:为什么要警告?为什么不出错?

tou*_*nom 2 c++ warnings undefined-behavior

考虑一下代码:

int& getValue()
{
  int i = 10;
  return i;
}
Run Code Online (Sandbox Code Playgroud)

这会导致编译器警告:

警告:引用局部变量`i'返回

我理解警告的原因.我正在返回一个局部变量的引用,一旦我超出范围就会被销毁.

我的问题是:为什么甚至允许这样做?为什么编译器不会简单地给出错误而不是警告?

Sha*_*our 5

它是未定义的行为,编译器甚至没有义务提供诊断,更不用说使它成为错误.该草案C++标准的部分1.4 实施合规说:

可诊断规则集包含本国际标准中的所有语法规则和语义规则,但那些包含"无需诊断"的明确表示法或被描述为导致"未定义行为"的规则除外.

这主要是因为编译器确定何时存在未定义的行为并且迫使编译器检测所有情况并不总是微不足道的,这将被视为过度负担.

虽然现代编译器捕的种种不良行为相当不错的未定义行为,有gccclang我发现下面的一组标志是有帮助的:-Wall -Wextra -Wconversion -pedantic.

您可以将这些变成您可以使用的错误-Werror,我强烈推荐.它迫使你理解为什么每个警告都会产生,并且有纪律可以找到更好的解决方案,从长远来看,这将为你节省很多痛苦.

注意,我们可能强制将错误用于可检测的未定义行为的一种情况是,当我们将constexpr函数的结果分配给constexpr变量时,因为常量表达式排除了未定义的行为.

所以下面的C++ 14代码:

constexpr int& getValue()
{
  int i = 10;
  return i;
}

int main()
{
    constexpr int &p = getValue();
    //...
}
Run Code Online (Sandbox Code Playgroud)

产生采用以下错误clang:

error: constexpr variable 'p' must be initialized by a constant expression
    constexpr int &p = getValue();
                   ^   ~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)