文章目录

    • 前言
  • 一、什么是引用
  • 二、引用的注意事项
  • 三、引用的两大妙用
    • 1.引用传参
    • 2.引用返回(只用于堆区或静态区变量的返回!)
  • 四、引用的底层实现
  • 五、引用 VS 指针(面试题)
  • 六、小彩蛋——送你一块语法糖

前言

在C语言中,我们学习过一个重要的概念——指针。今天,我们则要学习它在C++中的难兄难弟——引用。(一定要坚持看到最后哦,有甜甜的语法糖哦

一、什么是引用

首先,我们来看一段代码

 int a = 0;int* pa = &a;//指针int& ra = a;//引用

显然,我们今天的主角在第三行。

int& ra = a;

ra就是对变量a的引用
可我们要怎么理解引用呢?
举个例子:每个人都有小名,古人甚至还有名,号,子,字…
在C++的世界中,引用就是变量的小名(在上段代码中,ra就是a的小名)。
具体写法是:

引用对象的数据类型& 引用名=引用变量(大名)

二、引用的注意事项

1.一个变量可以有多个引用(一个人可以有很多小名)

 int a = 0;int& ra = a;int& goudan = a;int& wangerma = a;

2.引用也可以被引用
eg:李逵——黑旋风
但是我说:黑旋风又叫铁牛,实际上就是李逵叫铁牛。

 int a = 0;int& ra = a;int& rra = ra;

3.引用必须初始化(他叫铁牛,他是谁??)
int& ra;
4.引用一旦只向一个实体就不能再指向另一个实体了!!(劣势)
(水浒传中只有李逵能叫黑旋风,宋江就不行…)
既然如此,那请看下面这段代码,并告诉我在这里ra是否指向了b?

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

————————————————————————————————————————————
调试过程中(代码执行到第三行):

第四行执行后:

看到这里,是不是傻了?
其实,由于引用不能改变指向,这里的 ‘=’ 变成了赋值含义
也就是说,

int& ra = b;

这句话的含义是:把b的值赋给ra,由于ra指向a,因此a的值也随之变化。
(比如我说:黑旋风是傻子,那么同时也就是说铁牛是傻子,李逵也是傻子)
5.从语法的角度上讲,引用不占内存空间
可以说,a是这块内存空间的原名,ra是别名。

6.指针和引用赋值过程中,权限可以缩小或不变,但不能放大
权限不变:

int a = 0;
int& ra = a;//a,ra均既可读又可写const int b = 10;
const int& rrb = b;//b,rb均只可读

权限缩小:
可读可写——>可读不可写

int a = 0;//a可读可写
const int& rra = a;//rra可读不可写

权限放大 :

const int b = 10;
int& rb = b;//错误!

ps:权限的缩小仅针对引用而言,对原变量无影响
(引用只可读时,不影响原变量可读可写)
即 **rra++ **,a++正确,且原变量值改变时引用值也会改变!!!
用处
1).做参数时,如果实参不需要修改,使用 const& 能接受所有类型数据

void Func(const int& x);

不加 const 时就不能接受所有类型

void Func(int& x);

但是注意,普通传参则可以接受任何形式数据:

void Func(int x);

why?
这里和前面一样,使用这种方式传参时,创建了一个新的变量x,然后将实参内容拷贝进去,因此不是权限问题(这就是我们所说的,权限的缩小和放大仅针对指针和引用而言
2).使用const后,就可以引用常量了

const int& b=10;

3).使用const后,就可以实现 引用+缺省参数

void Func(const int& x=0)

4).在有隐式/显式类型转换的赋值过程中,必须使用const

double d=3.1415;
const int&a=d;

而,int& a=d 是错误的!
(原因与5).相同)
5).在函数普通传值返回的过程中,必须用const接收返回值

int Count()
{return 0;
}
const int& tmp=Count();

要想解释4),5),我们需要补充一些背景知识:
类型转换的过程中会产生一个临时变量保存转换后的值,因此表面上看是将d发生隐式类型转换后赋给a,实质上是将该临时变量中的值赋给a。
同理,在函数返回的过程中,也是通过一个临时变量保存返回值(这点我们将在下面提到),再将这个值赋给tmp。
该临时变量具有常性 ,因此在使用时必须加const。

三、引用的两大妙用

1.引用传参

原先我们知道的传参方式有两种——传值,传址
其中传址可以达到修改形参的同时修改实参的效果,现在我们有了一种新的方式——引用传参。
好处在于:
1.减少拷贝提高效率(不占用空间)
2.修改形参的同时修改实参
如下两处是等价的:

void Swap(int& left,int&right);
void Swap(int*left,int*right);

2.引用返回(只用于堆区或静态区变量的返回!)

这里我们首先要了解一种更常用的返回方式(传值返回):

int Count
{return n;
}

我们都知道,函数结束时,函数栈帧会销毁(使用权限还给操作系统),我们还能进行访问,但是其中数据的安全性已经无法保证。那么,返回值是如何拿到的呢?
*在传值返回时,程序结束前会创建一个临时变量(寄存器中或上层栈帧中),将返回值拷贝进该临时变量中保存下来。*所以,无论返回值是全局变量还是局部变量都能保证我们拿到正确的数据。
但是,引用返回只能用于堆区或静态区数据的返回!!!

static n=100;
int& Count
{return n;
}

因为引用返回并没有生成一个新的临时变量,而是将原变量的别名返回,因此当原变量销毁时,它的别名也不复存在,就会导致返回结果未知(拿到原数据/随机值/被覆盖的其他数据)
这样看来,似乎引用返回并没有什么优势呢。
NONO,
1.引用返回可以减少拷贝次数,提高效率。
2.引用返回可以修改返回值(这一点用处可就大了)
eg:实现顺序表中元素的展示和修改
现在可以使用一个函数完成

SLDataType& SlAt(SL* psl, size_t pos)
{assert(psl);assert(pos < psl->size);return psl->a[pos];
}
SLDataType& tmp=SlAt(&sl,5);
tmp=100;

四、引用的底层实现

前面说,从语法的角度讲,引用不占内存空间。
但是,底层上引用是通过指针(指针常量)实现的:
int& ra 等价于 int * const pa = &a
ps:指针常量——指针指向的对象不可修改(但对象的内容可以修改),书写方式为:
在 * 的右侧加上const
这里,也就解释了为什么引用的对象不能修改。

五、引用 VS 指针(面试题)

六、小彩蛋——送你一块语法糖


今天送大家一块名为auto的语法糖,让你初步感受一下C++的智能性:
1.auto可以根据右侧的数据类型来推测左侧的数据类型

int b=10;
auto a=b;

在这里,auto的这个用法优势体现还不深刻,但是当数据类型过长时,使用auto就可以有效地降低代码冗余度~
2.auto可自动判断循环结束,自动迭代
打印数组时,原先我们是这样写的:

int arr[] = { 1,3,5,7 };for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++){cout << arr[i] << ' ';}cout << endl;

可是,有了auto,我们就不再需要判断循环结束,自动迭代了(一定程度上避免犯错)

for (auto e : arr){cout << e << ' ';}cout << endl;

好了,本期的所有内容就到这里了,下期我们Linux见,bye~

C++入门——神奇的引用相关推荐

  1. C++入门——上卷(引用详解)

    C++入门--上卷 命名空间的探究 1,命名空间的定义 2,命名空间的使用 缺省参数 1.什么是缺省参数 2,全缺省与半缺省: 引用 1,什么是引用 2,引用的特性 3,常引用 4,使用场景 1,做参 ...

  2. 表达式类型的实现_程序员如何使代码简洁,Lambda表达式入门之四大引用(下篇)...

    享学课堂特邀作者:老顾转载请声明出处! 前言 上一篇介绍了lambda表达式的语法,今天老顾继续介绍 Lambda类型 Lambda表达式可以被当做是一个Object.Lambda表达式的类型,叫做& ...

  3. c++从入门到进阶--引用与常量

    一·常量表达式和constexpr与const 常量表达式概念:值不会改变并且在编译过程中就能计算出结果的表达式. ps:constexpr int a=20: constexpr int b=20+ ...

  4. jquerymobile入门(文件引用+多页面)

    一:文件引用: <meta name="viewport" content="width=device-width, initial-scale=1"&g ...

  5. C++入门学习:引用和常引用

    在C中有个关键字typedef 用来给类型(int, char *, double....)取别名,但不能给变量a取别名(int a:) 在C++新增了一个概念:引用--给空间取别名(变量名a就代表了 ...

  6. LEADTOOLS 入门教程: 添加引用并设置许可证 - C# .NET Core

    LEADTOOLS 是一个综合工具包的集合,用于将识别.文档.医疗.成像和多媒体技术整合到桌面.服务器.平板电脑.网络和移动解决方案中,是一项企业级文档自动化解决方案,有捕捉,OCR,OMR,表单识别 ...

  7. C++ C++基础语法入门总结(二)引用-内联函数-C++11新特性

    C++基础语法入门总结 C++引用 再谈引用和指针 C++内联函数 附加C++11新特性 auto关键字 基于范围的for循环 指针空值nullptr C++引用 引用:就是某一变量(目标)的一个别名 ...

  8. pythonpath怎么设置_Python编程该怎么入门 模块引用的方法有哪些

    Python编程该怎么入门?模块引用的方法有哪些?模块简单说就是一堆代码实现某个功能,Python为开发人员提供了丰富的模块,通过这些模块,我们可以快速开发出功能强大的程序.下面千锋就给大家分享Pyt ...

  9. 【引用】pygame菜鸟入门指南

    pygame菜鸟入门指南 本文引用自360doc,因为返回去找找原地址已经不可考,就声明一下引用.下文的很多点在我刚开始使用pygame两天就解决了很多的疑惑,留在这里是为了让日后的学习有一个参考.虽 ...

最新文章

  1. [mqtt]mqtt嵌入式移植
  2. 通过7个函数解密区块链(附代码)
  3. SAP SD基础知识之税(Taxes)
  4. 第二周项目2-就拿胖子说事
  5. python入门程序异常_Python入门基础(10)_异常_1
  6. netbeans调试_从NetBeans运行和调试WildFly Swarm应用程序
  7. Zookeeper深入系列-从Zookeeper中深入JMX原理
  8. html5 命运之轮生产
  9. SpringBoot2集成Quartz配置独立数据源
  10. php error unexpected,PHP异常Parse error: syntax error, unexpected错误解决方法
  11. opencapwap简要分析
  12. SCI论文的构思与常用结构
  13. spring 中使用tdd_通过JavaScript中基于属性的TDD的钻石方块
  14. gcc -m32报错的解决办法
  15. python中str,int,list,list(str),list(int)的相互转换
  16. 安卓学习笔记5.3 按钮、图像视图与图像按钮
  17. TensorFlow学习笔记(1)--TensorFlow简介,常用基本操作
  18. 升级windows11后wireshark显示wireshark Can‘t get list of interfaces: PacketGetAdapterNames报错
  19. 推荐7个高质量图片素材网站
  20. 北大青鸟java课后题答案_1 北大青鸟第一学期java上机练习答案 Develop 238万源代码下载- www.pudn.com...

热门文章

  1. 多普勒效应多径效应慢衰落、快衰落
  2. 领袖的七个非常重要的根性-余世维
  3. CMake问题:The CXX compiler identification is unknown
  4. Linux 之log 日志记录
  5. python3flask教程_Python3 Flask bootstrap教程(1)
  6. KubeEdge SIG AI 进展与规划
  7. 通过父级id 递归找到所有子类
  8. python rpa机器人_6个开源工具机器人过程自动化RPA工具
  9. 成功跳槽字节跳动,附答案
  10. vue watch监听中 immediate, deep, hander的作用