C++引用的理解与实现原理


如何理解引用 1

在使用上,我们要把引用当成另一个对象的“别名”

即看到一个引用,我们可以直接把它脑补成原来的对象

这样会衍生出引用的一系列特性(与指针相比):

  1. 引用被创建时必须被初始化,也叫“绑定”(指针则可以在任何时候被初始化)
  2. 不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)
  3. 引用初始化后不能改变引用的对象(指针则可以随时改变所指的对象)

引用如何实现

实际上如果查看汇编代码的话,引用是通过指针实现的

	int a = 55;
	int &b = a;
	int * const c = &a;

这一段代码会被编译器翻译为:

	movl	$55, -28(%rbp) 	// *(-28(%rbp)) =55; 即 int a = 55
	leaq		-28(%rbp), %rax
	movq	%rax, -16(%rbp) 	// -16(%rbp) = -28(%rbp); 即 int &b = a;
	leaq		-28(%rbp), %rax
	movq	%rax, -24(%rbp) 	// -24(%rbp) = -28(%rbp); 即 int * const c = &a;

可以看到虽然b是a的引用,但在实现上并不是简单的替换,而是生成了b的空间存储a的地址,和指针c的实现是相同的。即引用在实现上相当于是一个指针常量 。[指针常量与常量指针]


如何理解引用 2

我们可以看到,引用只是一种概念上的抽象,那在C++中为什么同时存在引用和指针呢?什么情况下使用引用呢?

结论1:C++的引用主要是为了支持运算符重载;指针的存在主要是为了兼容C语言。[为什么 C++ 有指针了还要引用?]
结论2:用户自定义类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用;对于内置(C-like)类型,按值传参会比按引用传参更高效。[内置类型传值效率高的原因]


引用的一些特性

有了这两层对引用的理解,我们就可以解释引用的下面这些特性了:

  1. 引用++ 是原来的对象执行自增(引用是对象的别名)
  2. sizeof(引用) 的大小是被绑定的对象的大小(引用是对象的别名)
  3. 一个类的成员变量带引用,此引用 必须显示在初始化列表初始化(引用在创建时必须初始化)
  4. 一个类的成员变量带引用,此引用 给类的大小贡献一个地址的长度(引用在实现上是指针)

posted @ 2021-04-24 13:50  HarryPotterIsDead!  阅读(1728)  评论(0编辑  收藏  举报