• 【C++】C++ 引用详解 ③ ( 函数返回值不能是 “ 局部变量 “ 的引用或指针 | 函数内的 “ 局部变量 “ 的引用或指针做函数返回值无意义 )






    一、函数返回值不能是 " 局部变量 " 的引用或指针




    1、引用通常做右值


    之前使用 引用 时 , 都是作为 右值 使用 , 引用只在 声明 的 同时 进行初始化时 , 才作为左值 ,

    // 定义变量 a
    int a = 10;
    
    // 定义变量 a 的引用 b
    int& b = a;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    引用 声明 并 初始化 之后 , 就没有当过右值 , 这是因为 引用 的本质 是 指针常量 , 其本身不可被更改 ;


    2、函数返回值特点


    函数 的 返回值 几乎很少是 引用 或 指针 ;

    函数 的 计算结果 经常是借用 参数中的 地址 / 引用 进行返回的 ,
    函数 的 返回值 一般返回一个 int 类型的值 , 如果 int 为 0 就是成功 , int 为其它数值 , 就是错误码 ;


    3、函数内的 " 局部变量 " 的引用或指针做函数返回值无意义


    如果 想要 使用 引用 或 指针 作 函数的计算结果 , 一般都是将 引用 和 指针 作为 传入的 参数 ;

    在 main 函数中 , 调用 函数 , 创建一个 变量 , 将 变量 的 地址 / 引用 传入 函数 , 在函数中通过 指针符号 或者 引用 , 直接修改传入的实参 , 也就是 修改 地址 / 引用 指向的 内存中的数据 , 该操作可以修改 外部 main 函数中的变量值 ;


    如果 想要 在 函数 中 , 返回一个 地址 / 引用 作为返回值 ,

    这个 地址 / 引用 是 谁的 ,

    • 如果 是 在 函数内部 栈内存 中创建的 变量的 地址 / 引用 , 那么 函数执行结束 , 返回时 , 该 栈内存直接被回收了 , 地址 / 引用 指向的内存空间可能就是随机值 ;
    • 如果 是 外部的 main 函数中的 变量 的 地址 / 引用 , 那么 肯定是从 参数中 传入的 , 那么这个 地址 / 引用 就不需要返回 , 函数内部修改 , 直接体现在了外部的变量中 ;

    因此 , 返回 局部变量 的 地址 / 引用 是无意义的 ,

    一般 函数 只 返回一个 int 值 , 表示 该函数 是否执行成功 , 如果执行失败 , 返回错误码 ( 在哪一步执行失败 ) ;


    如果 想要 在 函数中 , 返回 引用 / 指针 , 函数局部变量的 引用 / 指针 是返回不出来的 ,

    即使强行返回 引用 / 指针 , 也是当前 局部变量 被 分配的 栈内存 地址 ,

    该函数 执行完毕后 , 该 函数对应的 栈内存 会被回收 , 相应的 局不变量 地址 也有没有了意义 ,

    此时 , 再持有一个没有意义的 引用 / 指针 , 取出的值是随机无意义的值 ;





    二、代码示例 - " 局部变量 " 引用或指针做函数返回值测试



    下面的 int& getNum2() 函数 , 返回一个引用 , 该 引用 是 局部变量 的引用 ;

    下面的 int* getNum3() 函数 , 返回一个指针 , 该 指针 是 局部变量 的指针 ;

    上述两个函数是无意义的 , 获取到 函数 返回的 " 局部变量 " 的 引用 或 指针 , 然后获取地址 , 发现获取的都是随机值 , 都是无意义的值 ;

    num21 = -858993460 , *num3 = -858993460
    
    • 1

    代码示例 :

    // 包含 C++ 头文件
    #include "iostream"
    
    // 使用 std 标准命名空间
    //		该命名空间中 , 定义了很多标准定义
    using namespace std;
    
    // 导入 C 头文件
    #include 
    
    // 返回值是普通变量
    int getNum()
    {
    	int num = 10;
    	return num;
    }
    
    // 返回值是引用
    int& getNum2()
    {
    	// 此处的 num 是临时变量
    	// 该临时变量占用的 栈内存 空间 
    	// 在函数执行完毕后 , 会被回收 , 失效
    	int num = 20;
    	int& a = num;
    	return a;
    }
    
    // 返回值是指针类型
    int* getNum3()
    {
    	int num = 30;
    	return #
    }
    
    int main()
    {
    	// 函数返回 int 类型变量 赋值给 int 类型变量 num1
    	int num1 = getNum();
    
    	// 函数返回 int 类型引用
    	// 将 引用 赋值给 num2 变量
    	// 此处 使用 变量 接收引用值 , 
    	// 会自动将引用值对应的内存数据 10 取出来 , 赋值给变量
    	int num2 = getNum2();
    
    	// 将 int 类型引用 赋值给 num21 int 类型引用
    	// 这里只能记录地址 , 没有将值取出来保存
    	// 该地址马上就要被其它数据覆盖了
    	int& num21 = getNum2();
    
    	// 将 返回的 指针赋值给 int 类型指针
    	// 这里只能记录地址 , 没有将值取出来保存
    	// 该地址马上就要被其它数据覆盖了
    	int* num3 = getNum3();
    
    	// 再次调用一次 , 覆盖被回收的栈内存数据
    	// 这一步主要是混淆栈内存 , 使栈内存混乱
    	int num4 = getNum();
    
    	// 打印计算结果
    	printf("num1 = %d , num2 = %d , num21 = %d , *num3 = %d , num4 = %d \n", num1, num2, num21, *num3 , num4);
    
    
    	// 控制台暂停 , 按任意键继续向后执行
    	system("pause");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    执行结果 :

    num1 = 10 , num2 = 20 , num21 = -858993460 , *num3 = -858993460 , num4 = 10
    Press any key to continue . . .
    
    • 1
    • 2

    在这里插入图片描述

  • 相关阅读:
    微信小程序 —— 会议OA项目首页布局与Mock数据交互
    mybatis-plus异常:dynamic-datasource can not find primary datasource
    【framework-5】可能你需要加个if、加了变量
    C#.Net筑基-类型系统①基础
    Module加载的详细说明-保证你有所收获
    经典文献阅读之--Yolov7
    独立站3大火爆类目推荐
    基本的SELECT语句
    通用监控视频web播放方案
    Git常用命令diff和mv
  • 原文地址:https://blog.csdn.net/han1202012/article/details/132483858