Return局部变量的引用

Return the reference of the local variable

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

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() returns 引用局部变量,f1() 也能正常工作?

超出范围访问局部变量是未定义的行为。未定义的行为意味着程序可能会运行,它可能会出现段错误,它可能会打印垃圾值,一切。

底层原因1是局部变量位于堆栈上。堆栈属于进程的可写地址 space(至少在大多数(如果不是全部)像您这样的操作系统上是这样的)。程序可能会随心所欲地写入它。 但是,C++ 不支持写入堆栈。 C++ 只定义局部变量,不定义调用帧或 return 地址。它驻留在更高的抽象层次上。我所知道的唯一支持直接写入堆栈的语言是 Assembly。


1 C++ 标准没有以任何方式指定这个原因。

欢迎使用未定义的行为

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

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

因此,f1() 的 return 值是对超出范围的内容的引用,而 f2() 的 return 值是对的副本该函数的局部变量,可以。


然而,下降编译器应该警告你这一点,警告是这样的:

warning: reference to local variable ‘i’ returned [-Wreturn-local-addr]

请在编译器中启用 警告标志。 :)