小白看了直呼细节--CPP“引用”
C++新手村教学
- 引用
- 引用特性
- 使用场景
- 传值与传引用效率比较
- const常引用
- 引用与指针的区别
引用
类型& 引用变量名(对象名) = 引用实体;
首先我们看一个简单的程序:
#include <iostream>
using namespace std;
int main()
{int a = 1;int& b = a;cout << a << " " << b;return 0;
}
我们在 int 类型的后面接上了 & 符号,这个就代表引用。(&符号接在变量前面就叫取地址比如:int* b =&a )
那么引用是什么意思呢?
引用就是别名,比如孙悟空它就有很多别名,比如:美猴王、悟空、弼马温、齐天大圣都是它的名字,也都代表是孙悟空这个人物。
在Java中引用完全替代了指针,而在C++中没有完全替代指针,只是方便去替代(指针)做一些事情
如果我们要实现一个单链表,那么我们有了引用我们就可以这样:
某些算法书还会出现这样的我们以前没学引用所看不懂的代码:
引用特性
- 引用在定义时必须初始化
我们不能写下面这种代码:
int& ra ;
“没有初始化,直接写一个引用” - 一个变量可以有多个引用
int main()
{int a = 1;int& b = a;int& c = a;int& d = c;return 0;
}
- 引用一旦引用一个实体,再不能引用其他实体
意思就是我们已经int& ra = a;
那么就不能更改ra引用的对象(int& ra = b;这样是不允许的)
使用场景
- 做参数
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
输出型参数
- 做返回值
我们来看看下面的代码:
注意:
- 函数运行时,系统需要给该函数开辟独立的栈空间,用来保存该函数的形参、局部变量以及一些寄存器信息等
- 函数运行结束后,该函数对应的栈空间就被系统回收了
- 空间被回收指该块栈空间暂时不能使用,但是内存还在;
为什么会返回的是临时变量?
由上面图我们可以知道,我们返回的值是之前值的一份临时拷贝,在出Count函数栈帧在外面定义的临时变量。
这个临时变量如果比较小,可能在寄存器里面创建,如果比较大,那么就在上一层栈帧找个位置提前开辟好
如果是引用返回的话:
但是如果n不是存放在静态区,而是栈里面会怎么样?
这个代码就是有问题的!!!
内存销毁意味着什么?
1.空间还在吗? 空间还在,只是使用权不是我们的,我们存的数据不被保护
2.我们还能访问吗?能,只是我们读写的数据都是不确定的
(空间的申请和释放,就像是住酒店,退房了房间还在,只是不属于我们使用了,但是我们偷偷仿制一把钥匙还是能进入。空间读写数据,就像是我们丢下房间里面的东西,如果我们退房了,我们偷偷进去找,东西可能被打扫了,也可能下一任租客拿走了,东西还在不在是不却确定的)
结论:
出了函数作用域,返回变量不存在了,不能用引用返回,因为引用返回的结果是未定义的。
出了函数作用域,返回变量存在,才能用引用返回
传值与传引用效率比较
以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低
- 以值和引用的作为返回值类型的性能比较
#include <time.h>
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 1000000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 1000000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{TestReturnByRefOrValue();return 0;
}
传引用返回作用:
- 减少拷贝,提升效率
- 修改返回值
关于修改返回值,我们可以通过以前C语言的顺序表实现来了解
我们修改顺序表实现的SeqListModify
头文件:
size_t SLSize(SeqList* psl);
SLDataType& SlAt(SeqList* psl, size_t pos);
实现:
size_t SLSize(SeqList* psl)
{assert(psl);return psl->size;
}
SLDataType& SlAt(SeqList* psl, size_t pos)
{assert(psl);assert(pos < psl->size);return psl->array[pos];
}
int main()
{SeqList sl;SeqListInit(&sl);SeqListPushBack(&sl, 1);SeqListPushBack(&sl, 2);SeqListPushBack(&sl, 3);SeqListPushBack(&sl, 4);// 偶数*2;for (size_t i = 0; i < SLSize(&sl); ++i){if (SlAt(&sl, i) % 2 == 0){SlAt(&sl, i) *= 2;}}for (size_t i = 0; i < SLSize(&sl); ++i){cout << SlAt(&sl, i) << endl;}SeqListDestory(&sl);return 0;
}
- 以值和引用作为函数参数的性能比较
#include <time.h>
struct A { int a[10000]; };
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 1000000; ++i)TestFunc1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 1000000; ++i)TestFunc2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{TestRefAndValue();return 0;
}
引用做参数:
- 减少拷贝,提供效率
- 输出型参数,函数中修改形参,实参也修改了
const常引用
一般情况引用做参数都是用const引用
指针和引用赋值中权限可以缩小,但是不能放大
比如我们可以这样使用:
int a = 1;(a是可读可改)
int& ra = a;(ra也是可读可改)这是权限平移
const int b=2;(b只能读)
int& rb = b;(rb变成可读可改)权限放大,是错误的
const int& rb = b;(这样就能正常使用,变成只能读)
int c = 3; (可读可改)
const int& rc = c;(只能读)权限缩小,是正确的
下面这种情况也是典型的临时变量具有常性的例子:
引用与指针的区别
引用与指针的不同点:
- 引用概念上定义一个变量的别名,指针存储一个变量地址。
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
- 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
小白看了直呼细节--CPP“引用”相关推荐
- java开发crm框架_这可能是2020年度最完整、详细的Java高级框架+CRM课程哟,小白看完直呼过瘾!...
001_SpringMvc学习目标+MV核心思想 002_MVC框架对比+SpringMvc框架特点 003_SpringMvc内部请求流程解析 004_SpringMvc环境搭建与测试 005_Sp ...
- 一天实现用poi-tl导出word(饼图/柱状图、文字、表格、循环word),男朋友看完直呼好家伙
用一天的时间实现了要求的word的导出,包含表格.饼图.文字.柱状图,男朋友直竖大拇指,非让我给他讲,学会以后直呼抱大腿,害,这无处安放的优秀. 想研究的可以自己看一下接口文档 Poi-tl Docu ...
- 一篇文章让你彻底了解什么叫Netty!大牛看了直呼内行!
作者:java蜜蜜 链接:https://www.jianshu.com/p/1369b30b9f99 一.Netty到底是什么 1.从HTTP说起 有了Netty,你可以实现自己的HTTP服务器,F ...
- 《大厂面试》面试官看了直呼想要的简历
你知道的越多,你不知道的越多 点赞再看,养成习惯 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试点思维导图,也整理了很多我的文档,欢迎Star和 ...
- 四种代码洁癖类型,程序员看了直呼内行
很多程序员在写代码的时候 都有自己的独特的习惯 比较典型的就是"代码洁癖" 他二哥收集了一些代码洁癖症状 分了四个类型 来看看有没有你对应的吧 看到大家都如此极致的追求, 他二哥实 ...
- python判断奇偶数vscode_安利一波VSCode【vscode这样配置 戴夫看了直呼内行】
之前一直用vs2017写C#,最近转到vscode,发现生产力真的高很多,而且又能写python 又能写C#,真的很香 新人发帖,如有违规,请版主直接删帖 插件: ms-ceintl.vscode-l ...
- 四种代码洁癖类型,程序员看了直呼内行(文末经典书送)
很多程序员在写代码的时候 都有自己的独特的习惯 比较典型的就是"代码洁癖" 我收集了一些代码洁癖症状 分了四个类型 来看看有没有你对应的吧 一.极简断舍离型 二.距离产生美型 三. ...
- 恐龙的丁丁长什么样?它们是怎么啪啪啪的?这项研究网友看完直呼涨姿势.........
全世界只有3.14 % 的人关注了 爆炸吧知识 地球霸主的私生活 也藏不住了 昨天下午,超模君码字码得累了,决定放松一下,重温一下经典的<侏罗纪公园>. 当看到恐龙在平原上成群奔跑的画面时 ...
- java scanner以回车结束_大佬看了直呼内行,你当初Java刚入门是否也是这样写代码?...
1.集成开发环境 IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量.它可以极大地提升我们的开发效率.可以自动编译,检查错误. 2. ...
最新文章
- Visual C# .NET 2003 语言的改变
- try catch finally
- PYTHON -MYSQLDB安装遇到的问题和解决办法
- linux整理笔记之六:samba软件包使用
- 初级测试开发面试题_初级开发人员在编写单元测试时常犯的错误
- css的三个特性 背景透明设置
- Linux 驱动编译报错:error: macro __DATE__ might prevent reproducible builds [-Werror=date-time]
- 计算机能力提升研修总结ppt,信息技术能力提升研修总结
- JavaScript基础修炼(14)——WebRTC在浏览器中如何获得指定格式的PCM数据【华为云分享】
- HDU 4334 5-sum
- IT成长中的龟兔赛跑
- oracle中文谐音,Treasure的歌词中文翻译?? bruno mars 唱的treasure中文歌词谐音 谁懂啊?帮......
- android mtklog,Mtklog结构及分析
- pdf2Image Pdf文件存为jpg NodeJs实现
- Web Polygraph 安装
- 质数 素数 合数 因子
- 简历javaweb项目描述怎么写_JavaWeb开发简历项目经验怎么写
- 安徽大学计算机学院张静,安徽大学2011年国家励志奖学金获奖学生名单
- BZOJ3786: 星系探索(伪ETT)
- 网页制作存在的一些难点