返回本地变量的参考
问题描述:
在下面的代码中,演示了两个函数。 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()返回局部变量的引用?
答
欢迎来到未定义的行为!
这就是你正在做的。你访问一个超出范围的变量。但是,这可能是因为系统没有写入已经存在的值,这解释了行为。
这就是为什么在真实代码中找到这样的逻辑错误很难。因为你可能(非)幸运,并且变量具有正确的值(在该特定执行中)。
因此,f1()
的返回值是对超出范围的东西的引用,而f2()
的返回值是该函数的局部变量的副本,这是正确的。
然而,血统编译器应该提醒你注意这一点,与这样的警告:
警告:引用局部变量“我”返回[-Wreturn-本地地址]
请在您的编译器中启用您的警告标志。 :)
答
访问超出范围的局部变量是未定义的行为。未定义的行为意味着程序可能工作,它可能会出现段错误,它可能会打印垃圾值和所有内容。
低级原因因为这是局部变量位于堆栈上。堆栈属于进程的可写地址空间(至少在大多数情况下,如果不是全部的话,就像你的那样)。该程序可能会写入它就像它想。 然而,,写入堆栈是C++不支持的东西。 C++只定义局部变量,而不是调用帧或返回地址。它驻留在更高层次的抽象中。支持直接写入堆栈的唯一语言是Assembly。
其理由没有被以任何方式的C++标准指定。
因为你唤起了未定义的行为,这样做的天空是极限。 – 101010
因为你一直非常幸运...... – Chiel
你预计会发生什么? – emlai