【C++】引用做函数返回值时必须要注意

先看一段代码:

int& Add(int a, int b) {
	int c = a + b;
	return c;
}

int main() {
	int& ret = Add(1, 2);
	cout << ret << endl;
	return 0;
}

运行出来打印的值是没问题的。但这段代码没问题吗?

这里引用做了函数返回值,

首先将 Add(1, 2) 的返回值赋给 ret

ret 是个引用,

并没有实际空间,

而这段代码是能编过的,

所以 ret 会指向一块空间,

这块空间给谁了呢?

image-20220806221822623

很显然,这块空间是 Add 函数开辟给 c 的。

出了函数的作用域,

再访问那块空间实际上就越界访问了,

此时 ret 是界外的那块空间的别名,这样会有什么副作用呢?

看下面一段代码的运行结果:

image-20220806224257958

分析一下:

首先解释一下 ret1 = 7 的原因,

因为 ret1 指向的是 Add 函数开辟给变量 c 的那块空间,

当出了函数的作用域 c 就销毁了,

此时 ret 还是那块空间的别名,

销毁 c 的同时那块空间储存的值并没有被重置为随机值,

所以一开始给的那段代码打印出来的结果没问题。

但是,后来又调用了一次 Add 函数,

此时并没有将返回值赋给其他变量。

因为 ret1 只是一个别名,

它改变了说明它指向的那块空间储存的值改变了,

所以这两次调用 Add 函数所开辟的函数栈帧是没有变的,

创建局部变量 c 的位置也没有变。

第一次打印 ret1 的值是 7 没问题了,

但为什么第二次打印就成了随机值?

image-20220806224950254

这是调用第一次打印函数时的汇编代码,

当运行完黄标指向的那行之前时 ret1 的值就已经变了,

但还不是打印出来的那个随机值。

刚刚运行完的那一行调用了 call 指令,

此时去调用的是运算符重载函数 operator<<

函数调用要开辟栈帧,这里也不例外,

ret1 的值改变说明它指向的那块空间成了函数栈帧的一部分,

函数在执行过程中改变了那一块空间的值,

至于为什么 ret1 第一次打印出来的值是正确的,

这是因为在第一次改变 ret1 指向的那块空间之前就已经将 ret1 输出到屏幕上来了。

而我们可以看到后面又调用了几次 call 语句,

在后面开辟函数栈帧的过程中 ret1 指向的那块空间的值被多次改变,

第二次输出的随机值只是被改变之后的一个值,

ret1 之后可能还会再改变。


所以,如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LeePlace

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值