欢迎光临
我们一直在努力

函数返回的三种玩法:值、指针、引用

前面咱们学的是参数传递(调用函数的时候给东西进去),这里讲:函数 return 把东西送回来,也分三种:值、指针、引用

1)值返回(add 函数)

 int add(int m,int n)
 {
    int z=m+n;
    return z;
 }

✅ 原理: 函数内部的z是栈上局部变量。return 的时候,会把z里面的数值拷贝一份出去,交给 main 里的变量addRes。 函数结束之后,栈里面的 z 直接销毁、内存回收,没关系!因为值已经复制走了。

✅ 特点:简单安全,会拷贝一份数据;数据大的时候拷贝开销大。

2)指针返回(minus 函数)

 int* minus(int m,int n)
 {
    int* z=new int; // new:堆内存
    *z=m-n;
    return z;
 }

错误写法:

 int* minus(int m,int n)
 {
     int k=m-n;
     int* z=&k;
     return z;
 }

为什么崩?

k是栈局部变量,函数执行完,栈内存直接回收!你返回的地址指向一块已经被释放的垃圾内存,后面访问*z就是野指针,程序崩溃。

✅ 正确做法:用new在堆内存开辟空间。堆内存不会随着函数结束自动释放,所以地址拿出去还能用。

👉 代价:用完必须手动delete释放,不然内存泄漏!

3)引用返回(multiply 函数)

 long& multiply(int m,int n)
 {
    long* z=new long;
    *z=m*n;
    return *z;
 }

✅ 原理:返回的是堆里面这个变量的别名,不拷贝数据,效率高。

⚠️ 同样致命坑:绝对不能返回局部栈变量的引用!

 long& multiply(int m,int n)
 {
    long res = m*n;
    return res; // × res是栈变量,函数结束销毁
 }

返回的引用绑定到一个已经销毁的变量,悬垂引用,和野指针一样危险。


整体演示代码如下:

为了便于说明问题,在在参数传递递上都采用了值传递方式。

#include <iostream>
using namespace std;
int add(int, int);
int* sub(int, int);
long& multiply(int, int);
int main()
{
int x = 2, y = 3;
int addRes = add(x, y); //传值返回
int* subRes = sub(x, y); //传指针返回
long* mul = &multiply(x, y); //传引用返回。调用multiply,然后对返回的引用取地址,得到指针

cout << "2+3=" << addRes << endl;
cout << "2-3=" << (*subRes) << endl;
cout << "2*3=" << *mul << endl;
delete subRes; //释放堆内存
delete mul; //释放堆内存
return 0;
}
int add(int m, int n)
{
int z = m + n;
return z;
}
int* sub(int m, int n)
{
int* z = new int;
*z = m – n;
return z;
}
long& multiply(int m, int n)
{
long* z = new long;
*z = m * n;
return *z; //*z 是这块堆内存里的值,返回它的引用
}

 


关于引用的疑问:

引用返回值这里我想问,谁是本体?(就是谁是被引用的哪个?)

第一步:本体是谁?

new long 在堆上创造出来的那块 long 内存,它本身没有名字(无名变量)!

  • 指针 z:是一个指针变量,存着这个无名堆变量的地址

  • *z:代表【z 指向的这个堆上无名 long 变量】👉 这就是被引用的本体!

本体:堆里面那个没有名字的 long 变量(new出来的)

第二步:return *z; 发生了什么?

函数返回类型是 long&,意思是:返回这个本体的引用(别名)

🎃重点: 这个引用(别名)没有单独的变量名字

它是函数调用表达式 multiply(x,y) 本身 👉 multiply(x,y) 这个表达式,就是这个堆变量的别名!

看调用这一行:

 long* mul = &multiply(x, y);

  • multiply(x,y) = 那个堆 long 变量的别名(引用)

  • &multiply(x,y) = 对【这个别名对应的本体】取地址,拿到本体的地址

  • 把地址放进指针 mul

  • 对比普通有名变量的引用对比

    long a =6;  //本体是a

    long& ref  a;  //ref是a的别名

    回到这个multiply代码,只是本体没有名字
    普通版:本体有名字a,别名 ref
    你这个代码:本体是堆上无名变量,别名就是函数调用本身multiply(x,y),没有单独的ref变量写出来。

    希望可以帮助到大家,感谢观看,如果觉得文章对你有帮助的话,请点赞收藏关注支持一下博主😍,如有不足请指点,我及时改正!👻一起加油!嘻嘻😜

    赞(0)
    未经允许不得转载:171主机测评 » 函数返回的三种玩法:值、指针、引用
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址