【问题标题】:Why can this function return a C++ int reference? [duplicate]为什么这个函数可以返回一个 C++ int 引用? [复制]
【发布时间】:2020-03-12 21:42:18
【问题描述】:

最近,我在阅读C++ Primer,它说:

当一个函数完成时,它的存储空间被释放。一个函数之后 终止,对本地对象的引用引用不再有效的内存

因此,我在 Visual Studio 2019 中键入以下代码:

int& returnRef()
{
    int n = 2;
    return n;
}

int main()
{
    int ref = returnRef();
    cout << ref;
}

我认为这应该是一个大小写错误,但它没有并在命令上打印了正确的值。我很困惑。有对此的解释吗?

我是 C++ 新手。

编辑:

谢谢伙计们/姑娘们。看起来这个问题与编译器有关。我明白了。

顺便说一句,我发布了另一个关于在 vs2019 中启用编译器警告的问题: How can I enable compiler warnings in Visual Studio 2019?

【问题讨论】:

  • 我相信这并不能保证在每个平台上都有效(即,在每个编译器上产生相同的结果),并且在这种情况下,巧合的是,分配给局部变量的值仍然保留在内存中函数完成后。
  • 行为未定义,无需诊断。但是,大多数编译器都可以配置为在这种情况下发出警告 - 检查 VS2019 文档以查看是否有。
  • 在编写另一行 C++ 之前阅读this
  • 你说的“我认为它应该大小写错误”是什么意思?您的意思是您希望编译器发出错误消息或程序会出现运行时错误?

标签: c++


【解决方案1】:

“为什么这个函数可以返回一个 c++ int 引用?” - 它是有效的语法,因此编译器将编译它,但程序具有未定义的行为,因为它通过返回对临时的引用而破坏了语言的规则。这意味着您的程序无效,编译器可以为您程序的所有部分生成字面上的任何东西,并且不需要告诉你.

您不能指望每次执行不允许的操作时都会出现编译器错误,您只需了解所有规则并始终遵守它们。

【讨论】:

    【解决方案2】:

    C++ 标准并未明确声明此类代码应导致编译器诊断。但是,它仍然具有未定义的行为:它可能会或可能不会工作,它可能会在重新执行或在不同的机器上或使用不同版本的编译器重新编译时改变行为。 大多数编译器都会发出警告,只要您在编译时激活它们(例如,在 GCC 中使用 -Wall 或在 Visual Studio 中使用 /Wall)。例如 GCC 10 显示:

    prog.cc: In function 'int& returnRef()':
    prog.cc:4:12: warning: reference to local variable 'n' returned [-Wreturn-local-addr]
        4 |     return n;
          |            ^
    prog.cc:3:9: note: declared here
        3 |     int n = 2;
          |         ^
    

    【讨论】:

      【解决方案3】:

      这是未定义的行为,因为调用者在其生命周期结束后访问了 returnRef() 内的局部变量 n

      未定义行为的问题在于,它在大多数情况下似乎都可以正常工作。在这种情况下,在main() 读取之前,不会破坏n 占用的内存。但这不是保证。即使在这种情况下,在正确的时间传递给您的进程的信号也可能会在复制到ref 之前破坏n 的值。因此,请避免使用这种 UB,即使它看起来工作正常并且您的编译器不会抱怨它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-11
        • 2018-06-30
        • 1970-01-01
        • 1970-01-01
        • 2016-06-08
        • 2020-06-27
        • 1970-01-01
        • 2011-05-07
        相关资源
        最近更新 更多