C++-引用,inline,nullptr

news2025/1/22 9:13:21

一,引用

1.1引用的概念与定义

         引用不是新定义⼀个变量,而是给已存在变量取了⼀个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同⼀块内存空间。

引用的使用方式如下:

类型& 引用别名 = 引用对象。

1.2引用的特性

1.引用在定义时必须初始化。

2.⼀个变量可以有多个引用。

3.引用⼀旦引用⼀个实体,再不能引用其他实体。

int main()
{
	int a = 10;
	int c = 20;
	int& b = a;
	int& b = c;//编译器报错b多次重定义
	return 0;
}

        但这里我们需要注意,引用无法代替指针,因为引用无法改变指针指向,引用表面是传值,但本质也是传地址,然而这个工作由编译器来做,所以并不能由引用来执行。

1.3引用的使用

1.引用传参

之前我们数据结构部分的传参(拿栈来举例),我们在改变栈的各项数据时通常需要传栈的地址,有时候还需要去传二级指针,这就有些许麻烦,但引用可以适当简化:

void Swap(int& rx, int& ry)
{
	int tmp = rx;
	rx = ry;
	ry = tmp;
}
int main()
{
	int x = 0, y = 1;
	cout << x << " " << y << endl;
	Swap(x, y);//指针形式:Swap(&x,&y)
	cout << x << " " << y << endl;
	return 0;
}

还有这样:

void change(ST** st);
void change(PST& st);//PST为栈结构的指针

当然第二条我们也可以写成 ST*& st 也是可以的。

2.引用做返回值中减少拷贝提高效率(同时改变被引用对象)

我们先来对比下以下几种返回方式:

假设我的栈此时顶部数据为2,一个返回的是栈顶部的值,一个返回的是别名,乍一看好像并没有什么区别,引用返回值的场景相对比较复杂,我们在这里简单介绍⼀下,由于在返回值的时候,编译器会创建一个临时变量去储存返回值,所以第一种方式返回就会消耗一个整形的空间去临时存储,但引用不占实际空间,所以返回的仅仅是别名,不占用空间。

而且,返回引用还有个优点。就是可以改变此时的栈顶值,有人会说那我返回指针不也可以,请看如下代码示例:

STTop(st1) += 10;//引用改变值
*(STTop(st1)) += 10;//指针改变值

一目了然,明显引用的复杂程度更低,同时,如果我们返回的是指针,我们返回的时候还需要去创建临时变量去存放指针。

 4.const引用

这里我们需要非常注意权限放大的问题,对于const对象的引用,我们也必须要用const来修饰该引用对象,比如:

const int a = 10;
const int& ra = a;//正确引用

const int a = 10;
int& ra = a;//权限放大,引用对象可以改变被引用对象

还有当我们的右值直接等于表达式,或进行了强制类型转换,此时编译器会对右值先进行计算储存到临时变量中,然后再将临时变量赋给左值:

double b = 12.34;
int& a = b;//这里并非无法强转,而是强转的结果放在了一个const int类型的临时变量中
             导致编译报错

int c = 10;
int& e = c * 3;//这里与上面类似。临时变量为const int类型

当然,权限无法放大但可以缩小:

int a = 10;
const int& b = 0;

5.指针与引用的关系

C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。

1.语法概念上引用是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。

2.引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。引⽤在初始化时引⽤⼀个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象。

3.引用可以直接访问指向对象,指针需要解引引才是访问指向对象。

4.sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)。

5.指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。

二,inline内联函数 

        内联函数主要解决的是C中的宏定义的问题,我们先来回顾下宏的一些注意事项,比如我们定义一个两数相加的宏:

#define add(x,y) ((x)+(y));//正确写法

#define add(x,y) (x+y);//易错写法,如果传的是(x|y,x&y),由于
                       //位操作符的优先级低于+,所以无法达到预期目的

这里如果是宏,我们就需要多次的去加括号,显得很难受,但是我们写一个内联函数就可以解决这个问题:

inline int add(x,y)
{
   int a = x + y;
   return a;
}

但需要注意,inline对于编译器只是一个建议,如果你的函数定义代码过长(我们的vs一般是在9行左右) 他会屏蔽掉你的inline,不对函数进行展开。同时假如你使用的是vs2022,那么它默认是直接无视inline的,所以我们需要这样去设置我们的vs:

这时编译器便会将内联函数展开像调用宏一样去调用我们的宏,我们这里再用反汇编来证明它没有被展开:

展开的情况:                                                   没有被展开:

我们的反汇编结果可以看到它并没有右图中的函数地址的传递(函数的地址就是07FF6CAD313D9,h为十六进制的后缀)。

除此之外,我们还需要注意的就是,如果我们内联函数有声明的话,不能放在不同的文件之中,这样会报错,只能放在同一个文件中或内联函数直接定义在头文件中:

正确做法:

或:

亦或者是这样:

三,nullptr

在传统的C头文件(stddef.h)中我们可以看到:

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

在C++中,我们的NULL只是单纯的表示为0了,不能再表示空指针了,我们看下面一个例子就可以解释这种原因:

void f(int x)
{
	cout << "f(int x)" << endl;
}

void f(int* ptr)
{
	cout << "f(int* ptr)" << endl;
}

int main()
{
	f(0);
	f(NULL);
	return 0;
}

如果是C++的重载,我们会得到以下结果:

可以看到同时调用的是第一个F函数,如果我们将第二个改为((void *)0):

很遗憾C++不支持让void*转换成任意类型的指针,所以这里我们就需要用nullptr来代替我们C中的空指针,更换完后结果如下:

也就是说,这里的nullptr其实代替了我们C中的空指针NULL。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978381.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【带你入门生信】什么是生物信息学

生物信息学 生物信息学&#xff1a;利用应用数学、信息学、统计学和计算机科学&#xff0c;对生物学数据进行搜索&#xff08;收集和筛选&#xff09;、处理&#xff08;编辑、整理、管理和显示&#xff09;及分析&#xff08;计算和模拟&#xff09;&#xff0c;提取生物信息…

一键生成原创文案,轻松成为文案高手的方法

当下时代&#xff0c;文案写作对于各个企业推广产品和服务显得隔外重要。优秀的文案能够吸引用户的注意力&#xff0c;激发购买欲望&#xff0c;从而为企业带来更多的销售机会。然而&#xff0c;对于许多人来说&#xff0c;撰写出一篇吸引人的原创文案可能并不容易。但是&#…

【C++】C++11之新的类功能与可变参数模板

目录 一、新的默认成员函数 二、新的关键字 2.1 default 2.2 detele 2.3 final和override 三、可变参数模板 3.1 定义 3.2 递归展开参数包 3.3 逗号表达式展开参数包 3.4 emplace_back 一、新的默认成员函数 在C11之前&#xff0c;默认成员函数只有六个&#xff0c;…

2024华数杯选题建议-建模思路-代码论文助攻

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024 华数杯的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解析&#xff0c;帮助你全面理解并掌握如何…

C:关于static 和 extern 关键字的介绍-学习笔记

目录 1、作用域与生命周期 1.1 作用域 1.2 生命周期 1.3 变量的作用域和生命周期之间的关系 2、static 和 extern 2.1 static 修饰局部变量&#xff1a; 2.2 static 修饰全局变量&#xff08;包含extern的作用&#xff09;&#xff1a; 2.3 static修饰函数&#xff1a…

海思RTSP推流第二篇——海思平台和H264编码Demo

前言&#xff1a; 记得行内一个老师说过&#xff0c;基础不牢&#xff0c;地动山摇&#xff0c;对于海思的编码过程还是不是很熟悉所以回头把这个分析一遍。 海思平台&#xff1a; 官方手册&#xff1a;HiMPP IPC V2.0 媒体处理软件开发参考&#xff0c;里面有介绍海思IPC平台的…

polyfit曲线拟合

一、简介 polyfit函数是matlab中用于进行曲线拟合的一个函数。其数学基础是最小二乘法曲线拟合原理。曲线拟合&#xff1a;已知离散点上的数据集&#xff0c;即已知在点集上的函数值&#xff0c;构造一个解析函数&#xff08;其图形为一曲线&#xff09;使在原离散点上尽可能接…

深度学习 —— 个人学习笔记10(池化层、LeNet)

声明 本文章为个人学习使用&#xff0c;版面观感若有不适请谅解&#xff0c;文中知识仅代表个人观点&#xff0c;若出现错误&#xff0c;欢迎各位批评指正。 二十一、池化层 1、 最大池化层和平均池化层 与互相关运算符一样&#xff0c;汇聚窗口从输入张量的左上角开始&#…

打靶记录6——靶机EvilBox---One

靶机下载地址 https://www.vulnhub.com/entry/evilbox-one,736/学习记录 在进行目录爆破和文件爆破的过程当中&#xff0c;如果有发现新的路径&#xff0c;一定要对新的路径再次进行更深层次的爆破虚拟机出现问题就删除掉&#xff0c;重新导入虚拟机 目标: 获取两个flag&am…

如何准备专利申请书的摘要部分?

如何准备专利申请书的摘要部分&#xff1f;

基于概率神经网络的异方差不确定性估计

目录 摘要1 介绍2 预热3 分析3.1对称性和特征非线性3.2逆方差加权有效欠样本 4 方法5 实验5.1合成数据集5.2真实数据集6 结论 摘要 捕获任意不确定性是许多机器学习系统的关键部分。在深度学习中&#xff0c;达到这一目的的一种常用方法是训练神经网络&#xff0c;通过最大化观…

力扣SQL50 组合两个表 入门基础连表查询

Problem: 175. 组合两个表 select FirstName, LastName, City, State from Person left join Address on Person.PersonId Address.PersonId ;

AI说 | 如何入门AI行业,成为人工智能产品经理?(上)

这周在上海出差&#xff0c;划个水&#xff0c;发一篇之前写的文章&#xff0c;谈谈如何入门AI行业 另外&#xff0c;有朋友说我的文章读起来很累&#xff0c;自我反思&#xff0c;确实写的太长&#xff0c;后面我会在保证有趣或有干货的情况下&#xff0c;将文章内容尽量减短…

《深入浅出WPF》学习笔记四.提高效率,code snippets的使用

《深入浅出WPF》学习笔记四.提高效率,code snippets的使用 背景 再跟着视频教程学习Wpf的过程中,发现这个小技巧。很惭愧好几年开发经验&#xff0c;没用过这个东西。 这个信息差还是很让人头疼的&#xff0c;特别在此分享。 code snippets是什么 Code Snippets是插入代码…

Elasticsearch 未授权访问漏洞

Elasticsearch 未授权访问漏洞 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业级搜索…

zabbix监控中文乱码解决方案

zabbix切换中文后&#xff0c;会出现乱码情况&#xff0c;如下图&#xff1a; 解决方案如下&#xff1a; 1、找到字体 WinR打开运行&#xff0c;输入fonts&#xff0c;回车进入Windows字体目录&#xff0c;找到微软雅黑-常规字体&#xff0c;复制出来将文件名修改为msyh.ttf…

Substance Painter工具栏及快捷键

3 菜单栏_哔哩哔哩_bilibili ctrl右键左右滑动调整笔刷大小/左键流量 上下滑动有其他作用 线框显示工具 制作随机效果 Fill要配合遮罩使用 白色遮罩显示底色&#xff0c;黑色遮罩不显示底色 核心工具 图层关系 必须添加在蒙版的效果下 选择中蒙版 滤镜仅能添加在图层下 id图…

k8s中yaml文件的编写

目录 1.编写pod.yaml 2.编写deploment.yaml 3.编写service.yaml关联创建的pod 4.总结获取K8S资源配置清单文件模板方法 方法1&#xff1a;根据现有资源导出yaml文件修改配置&#xff0c;重新创建 方法2&#xff1a;根据现有资源&#xff0c;进入其配置中&#xff0c;复制…

Go语言实现多协程文件下载器

文章目录 前言流程图主函数下载文件初始化分片下载worker分发下载任务获取下载文件的大小下载文件分片错误重试项目演示最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;最近在开发文件传输相关的项目&#xff0c;然后顺手写了一个多协程文件下载器&#xff0c;代码非常精…

Cxx primer-chap12-Dynamic Memory

目前我们使用的对象都是语言本身代替我们管理其生命周期和作用域&#xff0c;例如global object、局部的自动变量和局部的static变量&#xff0c;除此之外&#xff0c;语言也允许我们创建动态分配的对象&#xff08;即运行时创建的对象&#xff09;&#xff1a;不同类型的对象&…