【问题标题】:Return the reference of the local variable [duplicate]返回局部变量的引用[重复]
【发布时间】:2016-01-19 00:39:18
【问题描述】:

在下面的代码中,演示了两个函数。 f1()返回函数作用域初始化局部变量的引用,f2()返回函数作用域初始化局部变量的值。

f2() 预计会很好地工作,因为本地初始化变量。值从栈传递到主栈。

f1() 预计不会起作用,因为局部变量的引用在函数范围之外是无用的。但是,这两个函数的输出似乎都可以。

这里是测试代码;

#include <iostream>
using namespace std;

// function declarations
int& f1();
int f2();

int main()
{
    cout << "f1: " << f1() << endl; // should not work!
    cout << "f2: " << f2() << endl; // should work

    return 0;
}

int& f1()       // returns reference
{
    int i = 10; // local variable

    return i;   // returns reference
}

int f2()        // returns value
{
    int i = 5;  // local variable

    return i;   // returns value
}

输出如下;

f1: 10
f2: 5

为什么 f1() 工作正常,即使 f1() 返回局部变量的引用?

【问题讨论】:

  • 因为你会唤起未定义的行为,而这样做是极限。
  • 因为你太幸运了...
  • 你预计会发生什么?
  • 未定义行为的一种可能性是它有时似乎工作正常。
  • 这比 'i++ + ++i' 有更多的重复 :(

标签: c++ reference local-variables return-by-reference return-by-value


【解决方案1】:

访问范围外的局部变量是未定义的行为。未定义的行为意味着程序可能会工作,可能会出现段错误,可能会打印垃圾值等等。

底层原因1是局部变量位于堆栈上。堆栈属于进程的可写地址空间(至少在大多数(如果不是全部)像您这样的操作系统上)。程序可能会随心所欲地对其进行写入。 然而,写入堆栈是 C++ 不支持的。 C++ 只定义局部变量,不定义调用帧或返回地址。它位于更高的抽象级别。我所知道的唯一支持直接写入堆栈的语言是汇编。


1 C++ 标准无论如何都没有指定这个原因。

【讨论】:

    【解决方案2】:

    欢迎来到未定义的行为!

    这就是你正在做的。您访问了一个超出范围的变量。但是,可能是系统没有在已经存在的值上写一些东西,这解释了这种行为。

    这就是为什么在实际代码中很难找到这样的逻辑错误。因为您可能(不)走运并且变量具有正确的值(在该特定执行中)。

    所以,f1() 的返回值是对超出范围的引用,而 f2() 的返回值是该函数的局部变量的副本,这没关系。


    但是,下降编译器应该警告您这一点,并发出这样的警告:

    警告:对局部变量“i”的引用返回 [-Wreturn-local-addr]

    请在编译器中

    启用警告标志。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 2021-04-28
      相关资源
      最近更新 更多