C++引用的使用场景和底层实现

1. 什么是引用:

  引用(referene)是一种复合类型,即基于其他数据类型的类型(指针亦是一种复合类型)。引用实质是给变量起了一个别名,而不是一个实体的类型,所以编译器不会给引用分配内存。同时,对引用的操作等效于对原变量的操作。

2. 定义一个引用:

  定义一个引用,在变量名前加上声明符&即可。
  (1)引用必须被初始化,即一个引用必须明确其引用的是谁。

int a = 1024;
int &b = a;		// b是一个对a的引用
int &c;			// 错误,引用未被初始化

  在上述代码中,b是一个引用,它引用的是a,故b的值是1024。但b不是一个实体的变量,它并不占用实际的内存,且所有对b的操作都将同等地作用在a上。

  (2)引用的目标不能更改
  定义一个引用时,程序把引用将其引用的变量值绑定(bind)到一起,而不是数值的拷贝,这是与普通的变量赋值是显然不同的。也正因为如此,引用在初始化后,便不能在更改引用的目标。

int a = 1024;
int b = 2014;
int &r = a;	// r等于1024
int &r = b;	// 报错,引用的目标不能更改

  (3)引用的目标必须时一个对象

int a = 1024;
int &b = a;	// 正确,a是一个对象;
int &c = b;	// 错误,引用本身不是一个对象;
int &d = 1024;	// 错误,1024是一个字面值,不是一个对象

3. 引用的使用场合:

  引用主要用在函数的参数传递中。
  (1)作为形参和实参:
  引用作为形参时,由于引用只是对象的别名,所以此时的形参是实参的别名。这样进行参数传递,形参在函数内部的变化都会作用在实参上。而不像用普通的变量进行参数传递,传值是单向的,只有使用指针才能实现双向的参数传递。
  同时,引用本身不占内存,所以使用引用进行参数传递时,不仅节省了内存开销,而且避免了拷贝构造的过程,提高了代码的执行效率。
  (2)作为返回值:
  引用作为返回值,优点与作为形参时类似,同样节省了内存开销,并避免了变量拷贝的过程。但此时需要注意引用对象的作用域问题。若返回一个引用,该引用的引用对象是函数内部的一个局部变量,则函数结束后,该变量的内存就销毁了,该变量也就不复存在,变量的引用也自然失去了意义。要避免这个问题,可以使用new一个新对象的方式来完成对该对象的引用。

4. 引用的本质:

  上面的部分阐述了引用的优点,那么它在底层究竟是如何实现的?其实引用在底层的实现和指针没有区别,同样占有一定的内存空间,但编译器对其进行了“包装”,在语言的层面上,展示给程序员的表现就是引用只是一个对象的别名,不占用任何内存。编译器具体的“包装”原理如下:
  对于对象val,r_val是它的引用,p_val是指向val的指针。则实际上,r_val和p_val均占有一定的内存,该内存中存储着val的地址,在32位机器上,该段内存占用4个字节的空间。r_val和p_val分别作为函数的形参时,在函数调用的过程中,编译器会对它们取地址,二者不同的是,编译器取引用地址时的汇编指令是mov,即取的是引用本身占据的内存中存储的内容,也就是引用对象的地址,在此就是val的地址,这也正是引用看上去不占用内存,只是对象的一个别名的原因;而编译器其去指针的地址时,执行的汇编指令是lea,即取的是指针本身占据的内存的地址,在此是p_val的地址,所以在使用指针时,要获得val的值,必须加上取内容操作符,即*p_val。(参考资料:c++引用和指针的实现
  根据以上分析可以知道,引用在底层就是指针,同样占据一定的内存空间;但在语言层面,经过编译器的“包装”(不同的编译器的实现方式不一定相同),引用“看上去”只是对象的一个别名,不占用任何内存。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值