C++学习心得:引用的详解
目录
一、引用的引入
1、值传递
2、地址传递
3、引用
二、引用的本质
1、初始化
2、引用赋值
三、引用的使用场景
1、作为函数参数
2、作为函数返回值
3、被函数的返回值初始化
4. 作为新引用变量的初始化值
四、引用的注意事项
五、引用和指针的区别
1、定义上的区别
2、值的区别
3、重复赋值
4、sizeof求值
5、自增(++)与自减(--)
6、多级
7、地址
8、安全性
六、转载
一、引用的引入
1、值传递
只是实参数据的拷贝,无法改变实参本身
void swap (int left, int right)
{int temp = left;left = right;right = temp;
}
2、地址传递
可以通过指针找到实参数据的地址,改变实参本身,但是容易出安全事故
void swap (int *_pleft , int * _pRight)
{assert (NULL ! = _pleft && NULL ! = _pRight) ;int iTemp = * _pleft;*_pleft = * _pRight;*_pRight = iTemp;
}
3、引用
是实参的别名,可以操纵实参本身,又不会涉及地址问题
void swap (int& left, int& right)
{int temp = left;left = right;right = temp;
}
二、引用的本质
1、初始化
引用(reference)不是新定义一个变量, 而是给已存在的对象取了 一个别名,本质上是一个常量指针。编译器不会为引用对象新开辟内存空间, 它和它引用的对象共用同一块内存空间 。
int num = 110;
int &number = num; //number指向num(是num的另外一个名字)
定义引用时,程序把引用和他的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成引用就将和他的初始对象一直绑定在一块(同生共死)。你无法将引用重新绑定到另外一个对象上。
2、引用赋值
number = 120; //把120赋给number指向的对象,此处即是赋给了num
int tmp = number; //与tmp = num执行结果一样
为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以引用绑定的对象作为初始值。
三、引用的使用场景
1、作为函数参数
可以简化指针,修改实参
void swap (int& left, int& right)
{int temp = left;left = right;right = temp;
}
2、作为函数返回值
1)不要返回局部变量的引用
主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
2)函数的调用可以作为左值
当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。例如,请看下面这个简单的程序:
#include <iostream>
using namespace std;double vals[] = { 10.1, 12.6, 33.1, 24.1, 50.0 };double& setValues(int i)
{return vals[i]; // 返回第 i 个元素的引用
}// 要调用上面定义函数的主函数
int main()
{cout << "改变前的值" << endl;for (int i = 0; i < 5; i++){cout << "vals[" << i << "] = ";cout << vals[i] << endl;}setValues(1) = 20.23; // 改变第 2 个元素setValues(3) = 70.8; // 改变第 4 个元素cout << "改变后的值" << endl;for (int i = 0; i < 5; i++){cout << "vals[" << i << "] = ";cout << vals[i] << endl;}return 0;
}
3、被函数的返回值初始化
#include <iostream>
using namespace std;int g_a; // 定义全局变量g_aint test() {g_a = 168;return g_a;
}int main()
{int &i = test();cout << i << endl; return 0;
}
编译报错:error C2440: “初始化”: 无法从“int”转换为“int &”
注:(有些编译器可以成功编译,但会给出一个warning)
分析:
这种情况下,函数test()是以值方式返回。
返回时,C++会在内存中创建临时变量并将g_a的值拷贝给该临时变量。
返回到主函数后,用临时变量来初始化引用变量i,使得i成为该临时变量的别名。由于临时变量的作用域短暂(在C++标准中,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束,也就是在语句int &i = test();之后) ,所以i面临无效的危险,很有可能以后的值是个无法确定的值。
如果真的希望用函数的返回值来初始化一个引用变量,应当先创建一个变量,将函数的返回值赋给这个变量,然后再用该变量来初始化引用:
int b = test();
int &i = b;
4. 作为新引用变量的初始化值
#include <iostream>
using namespace std;int g_a; // 定义全局变量g_aint& test() {g_a = 168;return g_a;
}int main()
{int &i = test();cout << i << endl; return 0;
}
这种情况下,函数test()的返回值不产生副本,而是直接将变量g_a返回给主函数。在主函数中,引用变量i用该返回值初始化,也就是说此时i成为变量g_a的别名。由于g_a是全局变量,所以在i的有效期内g_a始终保持有效,故这种做法是安全的。
四、引用的注意事项
1、允许在一条语句中定义多个引用,其中每个引用标识符都必须以&开头;
2、引用必须初始化,且初始化后不可改变引用指向。
3、因为引用本身不是一一个对象,所以不能定义引用的引用。
4、一个变量可以有多个引用,而一个引用只能给一个变量对象 。
5、引用的类型要和与之绑定的对象严格匹配(不严谨)。
6、引用只能绑定在对象上而不能和字面值或某个表达式计算的过程绑定在一起。
int i1 = 10, i2 = 20 ; //i1和i2都是int型
int &r1 = i1, &r2 = i2; //r1和r2都是引用
int &r3 ; //报错:引用必须初始化
int &r4 = i1, &r5 = i2; //r1, r4同为i1的引用,r2, r5同为i2的引用
int &r4 = i2, &r5 = i1; //报错:r4不能同时分别为i1和i2的引用
int &r6 = 10; //报错:引用类型的初始值必须是一个对象
double i3 = 3.14;
int &r7 = i3; //报错:此处引用类型的初始值必须是int型对象
五、引用和指针的区别
1、定义上的区别
- 指针即地址,因为指针是一个存储地址的变量,它指向内存的一个存储单元;
- 引用即别名,引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。
int a=1;int *p=&a;
//定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。
int a=1;int &b=a;
//定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单元。
2、值的区别
- 指针的值可以为空
- 但是引用的值不能为NULL,并且引用在定义的时候必须初始化;
3、重复赋值
- 引用定义时必须初始化,且在进行初始化后就不会再改变了;
- 指针可以不用, 正常情况下需初始化为NULL,且指针的值在初始化后可以改变,即指向其它的存储单元;
4、sizeof求值
- sizeof(引用)得到的是所指向的变量(对象)的大小、
- sizeof(指针)得到的是指针本身的大小;
5、自增(++)与自减(--)
- 引用自加改变变量的内容
- 指针自加改变了指针指向;
6、多级
- 可以有多级指针 (int **p;合法)
- 但是没有多级引 用,( 而 int &&a 是不合法的);
7、地址
- 引用的地址即所引用对象的地址。
- 指针的地址就是它自己的地址,是内存中的一块实实在在的另一块内存;
8、安全性
引用比指针更安全。不会出现像野指针这样的现象。
六、转载
引用的作用&引用与指针的区别 - 滴巴戈 - 博客园
C++ 引用作为函数返回值_a3192048的博客-CSDN博客_引用作为函数返回值
C++学习心得:引用的详解相关推荐
- java多线程学习-java.util.concurrent详解
http://janeky.iteye.com/category/124727 java多线程学习-java.util.concurrent详解(一) Latch/Barrier 博客分类: java ...
- ELK学习笔记之Logstash详解
0x00 Logstash概述 官方介绍:Logstash is an open source data collection engine with real-time pipelining cap ...
- Java中大数据数组,Java基础学习笔记之数组详解
摘要:这篇Java开发技术栏目下的"Java基础学习笔记之数组详解",介绍的技术点是"java基础学习笔记.基础学习笔记.Java基础.数组详解.学习笔记.Java&qu ...
- qstring如何初始化_学习QT之QString详解
学习QT之QString详解 QString类保存16位Unicode值,提供了丰富的操作.查询和转换函数.该类还进行了使用隐式共享.高效的内存分配策略等多方面的优化. 一.字符串常用操作 字符串的操 ...
- expect学习笔记及实例详解【转】
1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示: 1.1 首行加上/usr/bin/expect 1.2 spawn: 后面加上需要执行的shell命令,比如说 ...
- Python基础学习之 os 模块详解
Python基础学习之 os 模块详解 文章目录 Python基础学习之 os 模块详解 1. 路径操作 1.1 os.chdir(),切换当前工作目录: 1.2 os.getcwd(),返回工作目录 ...
- Activiti工作流学习之流程图应用详解
Activiti工作流学习之流程图应用详解 1.目的 了解Activiti工作流是怎样应用流程图的. 2.环境准备 2.1.相关软件及版本 jdk版本:Jdk1.7及以上 IDE:eclipse 数据 ...
- Quartz学习之Cron表达式详解
Quartz学习之Cron表达式详解 一.cron表达式结构 **二.各字段的含义** 解释: 注意要点: 三.示例 一.cron表达式结构 cron表达式从左到右(用空格隔开):**秒 分 小时 月 ...
- 【强化学习】Sarsa算法详解以及用于二维空间探索【Python实现】
Sarsa算法 Sarsa算法,是基于Q-Learning算法.改动其实很小. 本文工作基于之前的Q-Learning的项目,如果有疑问可以看下面两个问题: [强化学习]Q-Learning算法详解以 ...
- 机器学习,深度学习基础算法原理详解(图的搜索、交叉验证、PAC框架、VC-维(持续更新))
机器学习,深度学习基础算法原理详解(图的搜索.交叉验证.PAC框架.VC-维.支持向量机.核方法(持续更新)) 机器学习,深度学习基础算法原理详解(数据结构部分(持续更新)) 文章目录 1. 图的搜索 ...
最新文章
- java 画图 怎么清除已经画出来的图形_ppt小技巧——用paint3d画3d演示内容
- spring 初始化数据库
- 触摸事件练习 -- 手势解锁
- 如何把你的搜索引擎也加入到Firefox中
- Anychat的绝对路径与相对路径
- Nginx+Tomcat负载均衡访问网页出现报错HTTP Status 400 – 错误的请求
- 百度开源 FAQ 问答系统(AnyQ)安装---Linux(无docker)+小白编译AnyQ-dockerlinux[CentOs]
- Promise源码解析
- pycharm Debug调试
- 几台pc打造超级计算机,324台Mac Pro打造超级计算机
- JSK-389 同因查找【入门】
- 装双系统win10和android,厉害了小米6!不仅骁龙835,还支持安卓和win10双系统
- 11.微信小程序图片操作总结
- 在树莓派下使用dlib及resnet的人脸检测及识别
- 在使用vue脚手架之前你必须掌握的:vue的模版以及路由用法
- 【dgl框架】dgl.metapath_reachable_graph函数解析
- 1-1统计数字问题(C语言实现)
- 为什么很少有单片机机构?培训班一般多少费用?
- Microsoft Office word 2019教程 - word中的excel表格随着excel表格的变化而变化
- linux搜索文件内容中关键字,linux系统搜索文件中关键字的位置
热门文章
- 论文解读:Detach and Adapt: Learning Cross-Domain Disentangled Deep Representation
- 数据包络分析——二阶段网络带feedback
- python xgboost建模过程_python - Dask中的XGBoost建模 - SO中文参考 - www.soinside.com
- DWT文件怎么转换成html,dwg和dwt文件有什么区别?DWT又可以转换什么格式?-迅捷CAD转换器...
- c语言中Exec函数,子进程的执行 -- exec 函数
- 进度模型方法论,利用“削峰填谷”进行资源优化
- 「Thymeleaf页面在浏览器加载不出来」
- 使用docker搭建个人博客
- c语言公开课教案,9、祝福优质课一等奖教案
- iOS 名字按字母排序