当前位置: 首页 > ai >正文

C++篇(2)C++入门(下)

一、引用

1.1 引用的概念和定义

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

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

	int a = 10;int& b = a;  //b是a的引用

1.2 引用的特性

①引用在定义时必须初始化

②一个变量可以有多个引用

③引用一旦引用一个实体,就不能再引用其他实体

注意:引用不能改变指向,所以在链式结构中,引用无法代替指针

1.3 引用的使用

引用在实践中主要是用于引用传参和引用作为返回值中减少拷贝提高效率以及改变引用对象时同时改变被引用对象。引用传参和指针传参功能是类似的,引用传参相对更方便一些。当引用做函数形参时,修改形参会影响实参。

#define  _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;void swap(int* px, int* py)
{int tmp = *px;*px = *py;*py = tmp;
}void swap(int& px, int& py)
{int tmp = px;px = py;py = tmp;
}int main()
{int x = 1, y = 2;swap(&x, &y);swap(x, y);return 0;
}

引用作为返回值的场景比较复杂,这里简单讲一下使用场景,还有一些内容在后续的类与对象章节中会继续深入讲解。

首先我们需要知道一个知识,当函数传值返回时,其实是拷贝一份临时变量,然后把这个临时变量的值赋给其他变量,而这个临时变量具有常性(相当于被const修饰)比如现在有一数组,我们想把数组中每一个值都加1,那么在传值返回的值的基础上直接加1是编译不通过的,因为拷贝的临时变量具有常性,是不能被修改的,但是当我们传引用返回时就可以编译通过了。

因此,引用做返回值类型,一是可以修改返回对象,二是减少拷贝、提高效率。

既然引用有这么多的好处,那是否所有情况都可以把引用作为返回值类型呢?答案是不能!比如下面这段(伪)代码:

int& func()
{int ret = 0;//...return ret;
}

这个代码很不安全(因为ret的别名是不安全的)ret是局部对象,当func函数结束,ret就销毁了,这时返回ret的别名本质上是一种类似访问野指针的行为。如下图所示:

如果我们在main函数中用引用去接收这个函数的返回值,就会明显的出现异常。可以看到,我们并没有修改x的值,但是x的值从0变成了1。如下图:

那为什么之前修改数组元素可以传引用返回呢?因为我们用malloc在堆上申请了一块空间,并没有free掉,函数调用结束后这个数组一直都在。

1.4 const引用

C++中,可以引用一个const对象,但是必须要用const引用。const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。

int main()
{int x = 0;int& r1 = x;//权限可以缩小const int& r3 = x;const int y = 1;//权限不能放大//int& r2 = y;const int& r2 = y;const int* p1 = &y;//权限不能放大//int* p2 = p1;const int* p2 = p1;
}

需要注意的是,类似int& rb = a * 3;double d = 3.14,int& rd = d这样一些情况,a * 3的结果保存在一个临时变量中,在类型转换过程中也会产生临时对象存储中间值,也就是说,rb和rd引用的都是临时对象,而我们上面说了,C++中规定临时对象具有常性,所以这里触发了权限放大,必须要常引用才可以。

	const int& r4 = x * 3;double d = 3.14;const int& r5 = d;

1.5 指针和引用的关系

值得一提的是,在指令汇编角度上,引用是用指针实现的~

二、内联函数

在C语言阶段学过宏函数,编译器在预处理阶段替换,因此不用建立栈帧,本质上能够提效。但是,宏函数的缺点也很明显,宏函数的实现很复杂容易出错,并且不能调试。于是,C++设计了inline来替代C的宏函数。

用关键词inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数。inline对于编译器来说只是一个建议,也就是说,加了inline编译器也可以选择在调用的地方不展开,不同编译器关于什么时候展开的情况不同。inline适用于频繁调用的短小函数,对于递归函数或者代码相对多一些的函数,加上inline也会被编译器忽略。

inline int Add(int x, int y)
{return x + y;
}int main()
{int ret = Add(1, 2);cout << ret << endl;return 0;
}

注:inline不建议声明和定义分离到两个文件,分离会导致连接错误。

http://www.xdnf.cn/news/18240.html

相关文章:

  • 十二,数据结构-链表
  • Docker Compose命令一览(Docker Compose指令、docker-compose命令)
  • 【基础-判断】@CustomDialog装饰器用于装饰自定义弹窗组件,使得弹窗可以动态设置内容及样式
  • ubuntu下安装vivado2015.2时报错解决方法
  • 1-2前端撸码前的准备,包管理工具和环境搭建
  • SPI 机制深度剖析:Java、Spring、Dubbo 的服务发现哲学与实战指南
  • 基于Java虚拟线程的高并发作业执行框架设计与性能优化实践指南
  • ReAct Agent:让AI像人类一样思考与行动的革命性框架
  • 使用 FastAPI 的 WebSockets 和 Elasticsearch 来构建实时应用
  • Python HTML/XML实体处理完全指南:从基础到安全工程实践
  • mac电脑软件左上角的关闭/最小化/最大化按钮菜单的宽度和高度是多少像素
  • 阿里云ECS服务器的公网IP地址
  • 服务器硬件电路设计之 SPI 问答(一):解密 SPI—— 从定义到核心特性
  • 【机器学习深度学习】AI大模型高并发挑战:用户负载部署策略
  • 雷卯针对香橙派Orange Pi 3B开发板防雷防静电方案
  • 运用平均值填充后的数据进行模型预测
  • 计算机毕设Spark项目实战:基于大数据技术的就业数据分析系统Django+Vue开发指南
  • 函数式编程“闭包”概念深入解析
  • 【LeetCode 热题 100】279. 完全平方数——(解法三)空间优化
  • 应用在运行时,向用户索取(相机、存储)等权限,未同步告知权限申请的使用目的,不符合相关法律法规要求--教你如何解决华为市场上架难题
  • 手机截图如何优雅地放在word里
  • Hangfire定时部署(.NET 8 + SQL Server)
  • 读者写者问题
  • Linux多线程——线程池
  • Spark学习
  • MySQL基础操作
  • 网络连接的核心机制
  • HTML+CSS:浮动详解
  • Python 文件操作与异常处理全解析
  • Zemax光学设计输出3D