从c到c++——4:引用

前言   

    在《水浒传》中,梁山一百零八好汉,每个人都有一个响亮的外号,比如,当我们提到李逵和提到黑旋风提到铁牛时,本质上我们指的是同一个人。黑旋风江州劫法场,那李逵,铁牛也有江州劫法场的经历。引用也是这个道理。

从c到c++——4:引用_第1张图片


引用

        引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

从c到c++——4:引用_第2张图片

可以看出,a和b的关系就如同鲁迅和周树人的关系一样,a和b指向同一个内存空间。

合法的引用语法要求为:

  1. 引用必须初始化
  2. 引用定义后不能改变指向  (由于这条特性,引用不能完全代替指针)
  3. 一个变量可以有多个引用
int a = 10;

int& b = a;	//正确
int& c = 10;//错误,不能对常量引用
int& d;		//错误,没有初始化

引用做参数传参

        把引用作为函数的参数传递,由于他们两个指向的是同一块内存空间,可以通过修改引用的值来间接修改函数外变量的值。

        举个例子,在c风格的swap函数中,需要通过传地址来间接修改值,在cpp中使用引用就可以不调用指针实现。

//c
void swap_c(int* x, int* y)
{
	int tmp = *x;	*x = *y;	*y = tmp;
}
//c++
void swap_cpp(int& x, int& y)
{
	int tmp = x;	x = y;	y = x;
}

用引用来代替指针是一个不错的做法,可以显著提高代码可读性,但是由于引用不能修改指向,所以引用不能完全代替指针(如前序遍历链式二叉树需要递归更改指针的值,也就是地址引用显然不适合

引用做函数返回值

请注意,当引用做返回值时,地址必须在静态区,如全局变量,动态内存,否则会出现野引用的错误。

野引用:

从c到c++——4:引用_第3张图片

        显然,这是一段很狗屎的代码,引用ret1和ret2的地址为函数tmp中的一个地址,函数结束后,该内存中的值销毁,故ret1和ret2在tmp外查看时为一个随机值,且它们俩地址是一样的,幸亏引用的特性让他们不行被修改,不然他们和野指针的效果是一样的。

引用的底层实现原理

让我们写出这样一段代码。

int main()
{
	int x = 10;
	int& y = x;

	int m = 10;
	int* n = &m;

	system("pause");
	return 0;
}

然后转到反汇编

从c到c++——4:引用_第4张图片

有十分甚至九分的相似

引用和指针,在底层其实是一样的

同理,引用也会消耗内存来存储地址,只是这块内存找不到罢了。


一些吐槽

        不知道大家在阅读一些比较老的c语言数据结构书籍时有没有遇到这样的一段代码(应该在双向链表部分),它会给这么一段cpp的代码(请注意看它新建文件时给的后缀

//这是一个双向链表
typedef struct Node {
	struct Node* next;
	struct Node* prev;
	int val;
}LNode,*PNode;
void PushBack(PNode& pnode, int val)
{
	;//布拉布拉
}

按照原本c语言的逻辑:因为在PushBack函数中需要递归更改原链表的指针的值,需要向函数中一个二级指针,也就是*PNode。但是,或许是书的作者觉得指针不好理解,就给了一个c++的引用,这属实时有点离谱。


感谢观看!!! 

你可能感兴趣的:(c++,开发语言)