CPP--详解引用

225 阅读4分钟

引用的概念

什么是引用呢,简单的来说就是给变量起一个其他的名字,然后这个其他的名字和变量的地址是一样的,编译器并不会新开辟一块空间。比如给某人起一个绰号,其实这个绰号还是一个人。 例如下面就是一段简单的引用 ``

#include<iostream>
using namespace std;
int main()
{
	int a = 0;
	double d = 1.5;
	int& i = a;
	double& e = d;
	cout << a << endl;
	cout << i << endl;
	cout << d << endl;
	cout << e << endl;


}

输出结果

image.png

引用的作用在哪里

把引用作为参数

作用提升了效率,而且安全,还可以修改返回变量 举个例子

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

我们常常写交换函数,用指针进行交换,对于这个函数在调用的时候会开辟栈帧,把临时变量存进去,从而消耗了空间。我们可以使用引用

void Swap(int& a, int& b)
{
	int tmp;
	tmp = a;
	a = b;
	b = tmp;

}

这样的话避免新建指针变量,效率变得就比较高了。而且引用就是一个别名,所以变量可以很容易的被修改。

把引用作为返回值

我们先看这样一个简单的示例

int add(int a, int b)
{
	int c = a + b;
	return c;
}

一般来说这个函数可以完成正常的加法功能,但是存在一个问题,返回值并不是c,而是c的一个拷贝,这个函数在调用之后就会被销毁,变量也被销毁了。但是为什么能返回的,原因是因为这个c拷贝到了内存中,可以是寄存器里边,再由寄存器返回给调用者。如图

image.png

我们可以用引用作为返回值

int& add(int a, int b)
{
	int c = a + b;
	return c;
}
//引用返回就是直接返回c的值,也就是c的别名,而不是c的拷贝,这样就节约了空间

int main()
{
	
	int& res = add(1, 2);
	
	cout << res << endl;


}

image.png 看下边的一个问题

int& add(int a, int b)
{
	int c = a + b;
	return c;
}
//引用返回就是直接返回c的别名,创建一个函数栈帧,把c的别名保存起来

int main()
{
	
	int& res = add(1, 2);
	add(10, 20);
	cout << res << endl;


}

image.png 为什么是三十呢,这是因为函数再次调用的时候,函数栈帧被覆盖了

int& add(int a, int b)
{
	int c = a + b;
	return c;
}

int main()
{
	
	int res = add(1, 2);
	
	cout << res << endl;


}

这段代码存在问题,第一个是非法访问,因为add返回的是c的引用,当函数调用完毕后,c被销毁了,所以就非法访问了,第二个是如果清理空间,那么就会访问到随机值了,这就取决于编译器如何实现的了,我们再来看看下边的

image.png 这里的打印函数把c对应的栈帧给覆盖了,所以产生了随机值。所以使用引用作为返回值还是要慎重的。 这里要注意的是,如果返回引用的话,出了函数作用域,变量还没有返还给系统,那么就可以用,否则就不能用。 总结: - 引用作为返回值和传参数的时候,对于一些场景(传大对象深拷贝的时候)是可以提高性能的 - 另外可以用于形式参数的改变可以改变实参

常引用

int main()
{
	//const int a = 10;
	//int& b = a;
	const int c = 10;
	const int& d = c;
	int e = 10;
	const int& f = e;
	

}

第一段const int 表示这个变量是只读的,后边变成了int 这叫权限的放大,而第三段这个e又能读又能写,下边变成了const int,这个叫权限的缩小,就可以编译的过去

常引用的应用

void  ppp(int& x)
{
	cout << x << endl;
}

int main()
{
	//const int a = 10;
	//int& b = a;
	const int c = 10;
	const int& d = c;
	int e = 10;
	const int& f = e;
	ppp(f);
	

	

}

这里会出现错误原因是你传入了一个const int 的值给了int& ,权限被放大了,正确的方法应该是下面的

void  ppp(const int& x)
{
	cout << x << endl;
}

int main()
{
	//const int a = 10;
	//int& b = a;
	const int c = 10;
	const int& d = c;
	int e = 10;
	const int& f = e;
	ppp(f);
	

	

}

**总结一下就是,如果你的函数的参数不改变,参数是一个大对象或者是深拷贝,你还想传入引用,那么你就最好用 const type 作为参数类型。 **

注意的几个地方

  • 引用的时候必须要有初始值
  • 一个变量可以有多个引用
  • 引用一旦引用了一个变量,就不能引用第二个了

引用和指针的区别

  • 引用是一个别名,而指针是一个实体
  • 访问目标时,指针要解引用,而引用直接用
  • 指针可以有多级,而引用就一级
  • 指针可以指向空,而引用却不可以
  • sizeof的运算符是不同的,对于指针是四个字节,而引用要根据引用多大的变量了
  • 对于引用的自增就是加一,而指针就是指向下一段地址了