返回局部变量的引用

时间:2015-10-20 11:15:49

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

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

f2()预计会运行良好,因为本地初始化变量。值从堆栈传递到main。

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()返回局部变量的引用?

2 个答案:

答案 0 :(得分:7)

从范围外访问局部变量是未定义的行为。未定义的行为意味着程序可能正常工作,它可能是段错误的,它可能会打印垃圾值,所有内容。

1 的低级原因是局部变量位于堆栈上。堆栈属于进程的可写地址空间(至少在大多数(如果不是全部)操作系统上都是如此)。该程序可能会像它想要的那样写入它。 但是,写入堆栈是C ++不支持的。 C ++只定义局部变量,而不是调用帧或返回地址。它驻留在更高级别的抽象上。支持直接写入我所知道的堆栈的唯一语言是Assembly。

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

答案 1 :(得分:5)

欢迎使用 未定义的行为

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

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

因此,f1()的返回值是对超出范围的内容的引用,而f2()的返回值是该函数的局部变量的副本,这是正常的

然而,下降编译器应警告您这一点,并发出此类警告:

  

警告:引用本地变量'i'返回[-Wreturn-local-addr]

请在编译器中

启用警告标志。 :)