c++引用深入探讨
(偶然翻起自己的旧博,忽然发现大三的时候写的这篇文章,仔细看看觉得写的还是那么回事,所以赶紧搭救出来)
引用的声明: 基本格式:引用类型 &引用名=被引用对象
- &运算符:声明运算符& 跟取地址运算符&和位异或运算符&没有任何关系
- extern关键字:一般情况下 引用的声明必须指定被引用对象 唯一的例外是使用extern关键字
- const关键字:一般情况下 被引用对象必须是有效的左值对象 但是const关键字修饰的常引用类型允许被引用对象不是左值对象
引用的使用:引用可以被当作被引用对象的别名使用,单纯的引用是无意义的,引用主要应用于四个方面:
- 函数参数:可修改的实参,高效的复杂对象传递方式
- 函数返回值:不产生复制的返回值,返回左值类型的函数
- 运算符重载:为++ -- << >>等运算符提供了更贴近原意的重载方式
- 多态:代替指针使用,实现抽象类的引用
引用的深入探讨:现在开始进入正题
1.引用占内存空间吗?
如果引用只是一个别名的话 他不应该占有内存空间 我用下面这段代码来查看

代码
using namespace std;
void fa(){
int a[4];
cout<<a<<endl;
}
void fb(){
int a[4];
int &b=a[0];
cout<<a<<endl;
fa();
}
void fc(){
int a[4];
cout<<a<<endl;
fb();
}
int main()
{
fc();
getchar();
return 0;
}

这段代码里 我用了三个嵌套的函数调用 这样 fa 和fc的栈段就把fb夹在了中间 fb的栈段大小变化的话 会导致fc中a的地址偏移 但是并不是每个分配都会导致栈段增大的 所以应该先测试一下 确定a的合适大小 使得一旦声明变量 b的栈段就增大。
];注释掉的话
可以看到fc中输出的地址变了 fb没有变 那么 引用b显然占据了内存空间 我的代码在g++中编译,结果也是g++的结果。
2.引用的值不可改变吗?
一个已经初始化的引用类型对象 其引用的对象不可能被合法的改变。
前面一段代码展示给我们
引用确实占据了内存空间 ,了进一步了解其本质,我们必须获得它的地址。&取地址操作符显然是无法做到的 几乎每个学c++的人都会尝试用这种办法去取引用类型的地址,但得到的都是被引用对象的地址。
还从前面的例子入手 fb中 a的地址没有改变 fa中a的地址改变 那么 int &b的分配应该在 二者之间 于是 最可能的位置就是a中的a[4] 但输出之后我发现a[4]不是,因为数组a是跟栈逆向分配的 之后我试了这样的代码
void fb(){
int a[4];
int b=20;
cout<<a[-1]<<endl;
fa();
}
在我的编译器中 b跟a[-1]总是相等 于是 我把int b 替换成int &b=a[0]; ok 我发现它指向了一个貌似地址的东西。改变b的指向 发现a[-1]是随之变化的 现在 我几乎可以确定 a[-1]就是b了 再用一段这样的代码来检验
void fb(){
int a[4]={1,2,3,4};
int &b=a[0];
a[-1]+=4;
cout<<b<<","<<a[0]<<endl;
fa();
}
引用真的是不可改变的吗? 在这个例子中 我使b指向了a[1] 而不再是a[0]
3.引用和指针
从上面的例子看出 引用的内部实现和指针并无两样。如果参考其他语言的思想的话 可以得到结论:引用就是指针常量。 在c++中 引用在语法上与指针有着明显的差异 但是 他们并没有本质不同 引用是c++中实现的一种限制比较严格的常量指针 它在参与任何运算之前自动解引用。
在使用中 推荐尽量用引用代替指针,因为引用是一种比指针更安全的类型 并且有更清晰的语义(当然指针也有适合的语义)
4.其他语言
顺便一提,在C家的其他语言中 引用几乎被作为访问对象的唯一手段
C++:有指针 所有运算符会解引用 所有对象不作为引用 传递参数和返回值时如果不希望复制 则必须将形参指定为引用类型
C#: unsafe模式有指针 除了=之外的操作符会解引用 所有对象作为引用 传递参数和返回值时如果希望复制 则必须显式clone
Java:无指针 除了=之外的操作符会解引用 类似c#
javascript:无指针但是可以变通 除了=之外的操作符会解引用 没有提供复制传递的方法(郁闷)
c++引用深入探讨的更多相关文章
- Java强引用、软引用、弱引用及虚引用深入探讨
强引用.软引用.弱引用和虚引用深入探讨 为了更灵活的控制对象的生命周期,在JDK1.2之后,引用被划分为强引用.软引用.弱引用.虚引用四种类型,每种类型有不同的生命周期,它们不同的地方就在于垃圾回收器 ...
- iOS - 引用计数探讨
<Objective-C 高级编程> 这本书有三个章节,我针对每一章节进行总结并加上适当的扩展分享给大家.可以从下面这张图来看一下这三篇的整体结构: 注意,这个结构并不和书中的结构一致,而 ...
- 把《c++ primer》读薄(1-2前言+变量和基本类型)
督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 一:大小端的概念 Big-Endian和Little-Endian(见计算机存储的大小端模式解析) 二:浮点数的机器级表示 (见 ...
- 04--深入探讨C++中的引用
深入探讨C++中的引用 引用是C++引入的新语言特性,是C++常用的一个重要内容之一,正确.灵活地使用引用,可以使程序简洁.高效.我在工作中发现,许多人使用它仅仅是想当然,在某些微 ...
- java8 探讨与分析匿名内部类、lambda表达式、方法引用的底层实现
问题解决思路:查看编译生成的字节码文件 目录 测试匿名内部类的实现 小结 测试lambda表达式 小结 测试方法引用 小结 三种实现方式的总结 对于lambda表达式,为什么java8要这样做? 理论 ...
- [转] 深入探讨C++中的引用
引用是C++引入的新语言特性,是C++常用的一个重要内容之一,正确.灵活地使用引用,可以使程序简洁.高效.我在工作中发现,许多人使用它仅仅是想当然,在某些微妙的场合,很容易出错,究其原由,大多因为没有 ...
- Android业务组件化之现状分析与探讨
前言: 从个人经历来说的话,从事APP开发这么多年来,所接触的APP的体积变得越来越大,业务的也变得越来越复杂,总来来说只有一句话:这是一个APP臃肿的时代!所以为了告别APP臃肿的时代,让我们进入一 ...
- 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...
- PHP内核探索之变量(2)-理解引用
本文主要内容: 引论 符号表与zval 引用原理 回到最初的问题 一.引论 很久之前写了一篇关于引用的文章,当时写的寥寥草草,很多原理都没有说清楚.最近在翻阅Derick Rethans(home: ...
随机推荐
- 力扣142——环形链表 II
原题 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos ...
- SpringBoot系列之集成Dubbo示例教程
一.分布式基本理论 1.1.分布式基本定义 <分布式系统原理与范型>定义: "分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统" 分布式系统(d ...
- Ceph14.2.5 RBD块存储的实战配置和详细介绍,不看后悔! -- <3>
Ceph RBD介绍与使用 RBD介绍 RBD即RADOS Block Device的简称,RBD块存储是最稳定且最常用的存储类型.RBD块设备类似磁盘可以被挂载. RBD块设备具有快照.多副本.克隆 ...
- HTML横向滚动条和文本超出显示三个小圆点
我们这次要说的就是:现在有很多的公司以及很多的app软件经常使用的两个方法横向滚动条和文本超出三个小圆点 横向滚动条:顾名思义嘛,就是能够一块内容可以横着滑动. 文本超出三个小圆点:文本超出就是当文本 ...
- 怎样使我们的用户不再抵触填写Form表单?
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://blog.bitsrc.io/8-tips-for-an-awesome-sign ...
- CentOS 安装图形化界面后重启出现许可等事项操作
这是CentOS内核的初始设置页面,下面给出中文解释及操作方法. 1.CentOS Linux 7 初始设置(核心) 1)[!]许可证信息 (没有接受许可证) 请您选择[‘1’ 输入许可证信息 | ‘ ...
- 比特币学习笔记(一)---在windows下编译搭建比特币环境
最近打算研究下比特币源码,却发现这套源码正常情况下得在linux下编译运行,而我的机器是windows的. 怎么办呢? 起初打算用mingw和cygwin搞搞看,试了许久后发现行不通,必须转到linu ...
- 解决Maven项目中的无故报错的方法
解决Eclipse+maven中的无故报错 错误: One or more constraints have not been satisfied. Deployment Assembly跟java版 ...
- asp.net core 3.x 通用主机是如何承载asp.net core的-上
一.前言 上一篇<asp.net core 3.x 通用主机原理及使用>扯了下3.x中的通用主机,刚好有哥们写了篇<.NET Core 3.1和WorkerServices构建Win ...
- ubuntu下使用APT安装和卸载MySQL5.7
安装方式一: 向系统的软件仓库中列表中添加MySQL APT 仓库 去http://dev.mysql.com/downloads/repo/apt/.下载MySQL APT repository ...