「C++」引用详解

  • 引用的概念

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

使用方法如下:

int main()
{
    
    
	int a=10;
	int &b=a;//定义引用类型

	printf("%d\n",a);
	printf("%d\n",b);
	printf("%p\n",&a);
	printf("%p\n",&b);
	return 0;
}

运行一下,看结果如下,清楚看出二者地址相同
在这里插入图片描述
需要注意的一点是引用类型必须和引用实体是同种类型的,例如上面的代码a是int型的,那么引用类型必须也是int型。

  • 引用特性

1.引用在定义时必须初始化,例如int &a;如果在你的代码里出现这句代码编译器就会报错
2.一个变量可以有多个引用,这句话好理解,就像一个人可以有多个外号,可能你的同学叫你XXX,你在家家人叫你XX,一个道理
3.引用一旦引用一个实体,再不能引用其他实体

  • 常引用

看一组问题

//前提:
const int a = 10;
const int b = 10;
int c = 10;
double d = 1.11;

//下面这些代码谁对谁错??
int &r1 = a;
const int &r2 = b;
int r3 = b;
int *p1 = &b ;
const int *p2 = &b ;
int *p3=&c ;
const *p4=&c ;
int &r4 = d;
const int &r4 = d;

一个一个分析,在此之前先说一个赋值规则,权限可以缩小但是权限不可以放大
1.错误,a自己都不能随意更改,被引用后更不能随意更改了
2.正确,b不能随意更改,引用也不能随意更改
3.正确,只是将b的值赋给r3,就算更改r3也与b无关了
4.错误,b不能随意更改,权限不能放大
5.正确,同2
6.正确,c可以随意更改,引用后也一样
7.正确,权限缩小可以
8.错误,d是double型的,r4其实是引用了中间的那个临时变量
9.正确

  • 引用的使用场景

1.作参数

用一段简单的代码解释

void swap(&a,&b)
{
    
    
	int c=a;
	a=b;
	b=c;
}

int main()
{
    
    
	int x1=10,x2=20;
	swap(x1,x2);
	
	cout<<x1<<endl;
	cout<<x2<<endl;
	return 0;
}

2.作返回值

这段代码是否可以运行?

int Arr(int i)//改成int &Arr(int i)
{
    
    
	static int a[10]={
    
    0,1,2,3,4,5};
	return a[i];
}

int main()
{
    
    
	Arr(3)=10;
	cout<<Arr(3)<<endl;
	
	return 0;
}

不可以运行,原因是给Arr(3)赋值10的时候其实并不是真的给a[3]赋值了10,而是给它的拷贝赋值了10,改变它的拷贝对a[3]本体没有影响。修改后就可以了,因为此时是给a[3]的引用赋值了10,改变他的引用,本体也修改了,所以可行。
再提到一点,如果删去static是否可行呢?不可行,因为删去static的话,返回值出了作用域也就是函数Arr()就会被销毁。
所以你们觉得下面这段代码输出的是多少?3?其实是7,原因和上面一样,在函数返回时,离开函数作用域后,其栈上看见已经还给系统,因此不能用栈上的空间作为引用类型返回。如果以引用类型返回,返回值得生命周期必须不受函数限制。

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

int main()
{
    
    
	int &ret =Add(1,2);
	Add(3,4);
	cout<<"Add(1,2) is:"<<ret<<endl;
	return 0;
}

我们都知道以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递形参,就是实参的一份临时拷贝,这样效率是十分低下的,尤其是当参数或者返回值类型非常大时,效率更低,所以说我们在传值和返回时传引用效率更高。

  • 引用和指针的差别

前面说了,引用就是一个别名,没有独立空间,和被引用实体共用一块空间,但其实引用在底层实现上是有空间的,因为引用是按照指针方式来实现的。

那么引用和指针的不同之处是什么呢?

  • 引用在定义是必须初始化,而指针没有要求
  • 指针可以在任何时候指向任何一个同类型的实体,而引用不行
  • 没有NULL引用但是有NULL指针
  • 在sizeof中含义不同,引用结果为引用类型的大小,而指针始终是地址空间所占字节个数(32位平台占4个字节)
  • 有多级指针,没有多级引用
  • 访问实体的方式不同,指针需要显式解引用,引用是编译器自己处理

看上去指针比引用更加好用,但是为什么还是需要大量用到引用呢?因为引用比指针用起来相对更加安全

猜你喜欢

转载自blog.csdn.net/NanlinW/article/details/103051574