引用变量在下一行程序执行后显示未找到的行为



下面是一段代码,显示了同一操作的不同输出。为什么我在下面的cout中得到不同的值?请分享您对此的看法。

#include<iostream>
#include<stdio.h>
using namespace std;
int const& f(int i=9, int j=99, int=999) {
    return i;
}
int main() {
    const int &k = f();
    //cout<<" n hello n"; //If I enable this cout thenn all the below will only print some junk values(even if I remove the const!!).
    cout<<"n"<<k<<" "<<k<<" "<<k;  //prints "9 9 9"
    cout<<"nn"<<k<<" "<<k<<" "<<k<<"n";  //prints "134520896 134520896 134520896", some garbage value. why is it so?
    cout<<"nn"<<k<<" "<<k<<" "<<k<<"nn";    //prints "134520896 134520896 134520896", some garbage value. why is it so?
}

如果i的生命周期仅限于函数调用的范围,那么为什么它在第 13 行正确打印了三次,为什么当我取消注释第 12 行时没有?

请分享您对此的想法,并附上详细的解释会有所帮助。

这是未定义的行为,因此任何事情都可能发生。正如您所说,i的生存期仅限于函数的范围,因此引用不是对有效对象的引用。

可能,以前由i占用的堆栈内存直到下一次函数调用operator<<才会被覆盖。如果编译器在第一次函数调用之前计算第一行中的所有参数,则它们仍将具有函数留下的值。之后,内存被覆盖,所以你看到垃圾。

好吧,您返回的是对整数的常量引用。问题是,该引用引用的对象可能不再有效。我是f()本地的,当该功能结束时,计算机可以自由地使用我曾经驻留的内存位置做任何它想做的事情。

这是 : 未定义的行为。

在此语句中

const int &k = f();

函数 F 返回的引用无效,因为局部变量 i 的生命周期在退出函数后完成。

因此,作为函数返回的引用和名为 k 的引用都是无效的。

因此,该程序具有未定义的行为。

但是,如果您通过以下方式重新定义函数,则可以使程序格式正确

int f( int i=9, int j=99, int=999 ) 
{
   return i;
}

在此案例陈述中

const int &k = f();

将是有效的,并且临时对象将处于活动状态,而引用处于活动状态。

问题是当你调用时

const int &k = f();

编译器将其转换为

const int &k = f(int i=9, int j=99, int=999);

在 ASM 中,它将是这样的

push 9
push 99
push 999
push some registers
call f
pop some registers
pop //your 999 was here
pop //your 99 was here
pop //your 9 was here

因此,在 k 中,您会在堆栈中收到一个地址。它之前包含 9 个,但现在 9 个已经弹出。所以任何东西都可能在这里。这就是你收到垃圾的原因。

最新更新