💓博主CSDN主页:杭电码农-NEO💓
⏩专栏分类:C++初阶之路⏪
🚚代码仓库:NEO的学习日记🚚
🌹关注我🫵带你学习排序知识
🔝🔝
1. 前言
C语言中有一利器: 指针
而C++中增加了另一利器: 引用
这两个板块的存在
极大了提升了C/C++的可用性!
本篇文章将给大家详细讲解引用
并且分析引用和指针的联系和区别
最后给大家拓展C++中的空指针
2. 引用的概念
概念:
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间
比如说孙悟空又叫
孙行者,齐天大圣,斗战胜佛
李逵又叫黑旋风,铁牛
类型& 引用变量名(对象名) = 引用实体
引用符号:&
举个例子来说明:
int a = 10;
int& ra = a;//<====定义引用类型
printf("%p\n", &a);//打印地址
printf("%p\n", &ra);
打印出来的地址相同
并且引用值改变,原先的值也会改变!
int a = 10;
int& ra = a;
cout << ra <<' '<< a;
cout << endl;
ra = 20;
cout << ra << ' ' << a;
a的值会从10被修改成20
3. 引用的特性
引用特性:
- 引用在
定义时必须初始化
- 一个变量可以有多个引用
- 一旦引用一个实体,就不能引用其他实体
特性讲解:
int a = 10;
int& ra; // 没初始化,会报错
int& ra = a;
int& rra = a;
int& rrra = a;
//这三个都是a的引用,只要其中一个
//发生改变,其他三个也会改变
printf("%p %p %p %p\n", &a, &ra, &rra, &rrra);
int a = 10;
int& ra = a;
int b = 20;
ra = b; //这条语句的意思是将b的值赋值给a
//而不是ra从a的引用变成b的引用
cout << ra << ' ' << a << ' ' << b;
cout << endl;
printf("a的地址:%p ra的地址:%p b的地址:%p", &a, &ra, &b);
可以看见ra的地址和a是一样的
一旦引用初始化后就不能改变引用对象
4. 常引用
顾名思义就是引用常量
但是常量具有不可修改性
所以引用一个常量时要加上const
const int a = 10;
//int& ra = a; // 该语句编译时会出错,a为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错,b为常量
const int& b = 10;
double d = 12.34;
//const int& rd = d; // 该语句编译时会出错,类型不同
const double& rd = d;
并且引用的类型要对上
int类型的引用对应int&
double类型的引用对应double&
…
5. 使用场景
5.1 引用做函数参数
引用做函数参数
之前在写C程序的交换函数时
因为形参是实参的一份拷贝
想要改变实参就要传地址
而现在有了引用就不用传地址了!
void Swap(int& left, int& right)//交换函数
{
int temp = left;
left = right;
right = temp;
}
int a = 10;
int b = 20;
Swap(a,b);//因为形参为引用,所以这传的是a,b的引用
注: 引用传参时,不用加符号&& 符号放在类型后面时是引用
其他地方& 符号都是取地址!
5.2 引用做函数返回值
引用做返回值
引用做返回值时
可在函数外面修改函数里面的内容
前提是引用的变量出了函数不会销毁
static int n = 0;
int& Count()
{
n++;
n++;
return n;
}
int& tmp = Count();
tmp = 20;
cout << tmp << ' ' << n;
由于局部变量出了作用域会销毁
所以这里在函数中定义的是静态变量
并且修改tmp的值会改变n的值
6. 注意事项
下面这段代码不能用传引用返回:
int& Add(int a, int b)
{
int c = a + b;
return c;
}
因为函数调用完后C就被销毁了
而将C的引用返回后
会有类似于使用野指针的风险
总结:
如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。
7. 传值和传引用效率分析
作为函数返回值的比较
- 传值返回分析
首先,传值返回并不是单纯的将
返回值直接传给外面的变量
而是会生成一个中间变量的拷贝
这个中间变量再将值拷贝给外面的变量
(注:在栈帧创建与销毁有详细介绍)
画图理解:
然而传引用返回没有这么复杂的过程
综上所述:
因此用值作为参数或者返回值类型
效率是非常低下的
尤其是当参数或者返回值类型非常大时
效率就更低
8. 引用和指针的联系
它们的联系:
语法层面上
引用在语法概念上就是一个别名
和实体共用一份空间
底层实现上
引用在底层实现上是有空间的
因为引用是按照指针的方式来实现的
也就是指针的底层汇编和引用一样
左边为引用,右边为指针:
9. 引用和指针的区别
- 引用概念上定义一个变量的别名,指针存储一个变量地址。
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
- 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
10. 总结以及拓展
总结:
总的来说,C++中更喜欢用引用
特别是在一些容器中,如:栈,队列
使用引用的效率会提高许多
在类和对象中引用也是重量级的存在
所以说引用十分的重要!
拓展:
C++中的空指针不用NULL
而是用nullptr来替代(nullptr是关键字,使用时不用包头文件)
文章来源:https://www.toymoban.com/news/detail-521309.html
为了提高C++代码的可读性
在后续表示指针空值时
建议最好使用nullptr。文章来源地址https://www.toymoban.com/news/detail-521309.html
到了这里,关于【C++初阶(三)】引用详解(对比指针)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!