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




1、引用通常做右值


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

// 定义变量 a
int a = 10;

// 定义变量 a 的引用 b
int& b = a;

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


2、函数返回值特点


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

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


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


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

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


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

这个 地址 / 引用 是 谁的 ,

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

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

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


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

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

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

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





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



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

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

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

num21 = -858993460 , *num3 = -858993460

代码示例 :

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

// 返回值是普通变量
int getNum()
{
	int num = 10;
	return num;
}

// 返回值是引用
int& getNum2()
{
	// 此处的 num 是临时变量
	// 该临时变量占用的 栈内存 空间 
	// 在函数执行完毕后 , 会被回收 , 失效
	int num = 20;
	int& a = num;
	return a;
}

// 返回值是指针类型
int* getNum3()
{
	int num = 30;
	return &num;
}

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;
}

执行结果 :

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

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

09-16 09:29