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

2023-08-25 19:56:45





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




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 . . .

在这里插入图片描述

更多推荐

什么是浏览器的同源策略(same-origin policy)?它对AJAX有什么影响?

聚沙成塔·每天进步一点点⭐专栏简介⭐浏览器的同源策略(Same-OriginPolicy)⭐同源策略对AJAX的影响⭐写在最后⭐专栏简介前端入门之旅:探索Web开发的奇妙世界欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一

WebGL 常用术语整理

目录Aα混合(alphablending)α值(alphavalue)环境光(ambientlight)连接(attach)attribute变量(attributevariable)B绑定(bind)缓冲区(buffer)缓冲区对象(bufferobject)C画布(canvas)裁剪(clipping)颜色缓冲区(

React 如何拿时间戳计算得到开始和结束时间戳

获取需要的时间戳(开始and结束时间戳)调用如下方法就行:functiongetWantTimestamp(props){//当前时间constnowDate=parseInt((newDate().getTime()/1000).toString());//当前时间switch(props){//当前时间时间戳cas

网站整站优化-网站整站优化工具

您是否曾为您的网站在搜索引擎中的排名而感到焦虑?是否苦苦思考如何提高流量、吸引更多用户?什么是整站优化。简而言之,它是一项用于提升网站在搜索引擎中排名的策略和技巧。通过对网站的内容、结构、速度等方面进行优化,可以使网站更容易被搜索引擎收录,从而提高在搜索结果中的排名。而147SEO工具是一款为您提供整站优化解决方案的强

【C++】搜索二叉树底层实现

目录一,概念二,实现分析1.插入(1.)非递归版本(2.)递归版本2.打印搜索二叉树3.查找函数(1.)非递归版本(2.)递归版本4.删除函数(重难点)易错点分析,包你学会(1.)删除目标,没有左右孩子(2.)删除目标,只有一个孩子(3.)删除目标,有两个孩子代码(1.)非递归版本(2.)递归版本5.析构函数6.拷贝构

两数之和 三数之和【基础算法精讲 01】

灵神算法基础算法精讲[01]:两数之和三数之和【基础算法精讲01】_哔哩哔哩_bilibili167.两数之和II-输入有序数组链接:力扣(LeetCode)官网-全球极客挚爱的技术成长平台思路:采用双指针的思想,因为给出的数组是有序的,n=len(numbers),定l=0,r=n-1;如果s=numbers[l]+

监控数据的采集方式及原理

采集方法使用频率从高到低依次是读取/proc目录、执行命令行工具、远程黑盒探测、拉取特定协议的数据、连接到目标对象执行命令、代码埋点、日志解析。读取/proc目录/proc是一个位于内存中的伪文件系统,而在该目录下保存的不是真正的文件和目录,而是一些“运行时”信息,Linux操作系统层面的很多监控数据,比如内存数据、网

Go编程规范

文章目录注释转义符定义变量方法一:指定变量类型,声明后若不赋值,使用默认值方法二:根据值自行判定变量类型(类型推导)方法三:省略var,注意:=左侧的变量不应该是已经声明过的,否则会导致编译错误[`推荐`]全局变量和局部变量fmt.Printf查看变量常量iota定义函数多行书写参考注释//单行注释/*多行注释第一行第

javabean项目专项练习(1) 文字格斗游戏

main中是这样写的如下是character类的描述总结一下(个人):这是一题面向对象的编程,个人编程后感是:核心就是在于自己会不会取定义一个类,如果是多个对象(同一个类),能不能捋顺类的方法的关系,个人觉得黑马程序员up主给出来的分析方法特别好用.步骤:先把在类里该该弄得弄好,然后看题目需求的打印方法,我们可以根据题

idea Terminal 回退历史版本 Git指令 git reset

——————强制回滚历史版本——————一、ideaTerminal第一步:复制版本号(右击项目–>Git-->ShowHistory-->选中要回退的版本–>CopyRevisionNumber,直接复制;)第二步:ideaTerminal(确认项目)输入指令:gitreset--hard版本号示例:gitreset

【计算机组成原理】第一章部分课后题

冯·诺依曼型计算机的主要设计思想是什么?它包括哪些主要组成部分?冯·诺依曼型汁算机的其本没计思想为:①以二进制形式表示指令和数据②程序和数据事先放在存储器中,计算机在工作时够高速地从存储器中取出指令加以执行③由运算器、控制器、存储器、输入设备和输出设备五大部分组成计算机硬件系统它的主要组成部分为:运算器、控制器、存储器

热文推荐