C++引用知识详解

一、引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间
引用在C++中使用‘&’符号来实现,例如:
int main()
{
	int a = 10;
	int& ra = a;
	cout << a << "==" << ra;
	return 0;
}

输出结果:

这里的 “int& ra = a;”就是给a取了一个别名叫做ra,这里要注意的是,因为ra是a的别名,故ra和a本质上就是一样的,故它们所在的地址也是一样的:

int main()
{
	int a = 10;
	int& ra = a;
	cout << &a << "==" << &ra;
	return 0;
}

输出结果:

如果要对指针引用,同样在后面加一个“&”即可,例如:

int main()
{
	int a = 10;
	int* b = &a;
	int*& c = b;
	cout << b << endl;
	cout << c << endl;
	return 0;
}

输出结果:

这时就会有人问了:为什么不直接写成"int*& c=&a;",原因很简单,a的地址是一个标准的常量,引用是不能引用常量的。

切记:引用类型必须和引用实体是同类型的,否则会发生编译错误

二、引用的特性:

1、引用在定义时必须初始化。一个引用被定义就是为了给一个变量取别名的,因此一旦定义就一定得有一个变量被其所引用。                                                                                                     

2、一个变量可以有多个引用。这个很好理解,就像一个人可以有多个别名,但有人可能还会问:那我可以给引用取别名吗?当然可以。给引用取别名其实就相当于给变量又取了一个别名。

3、引用一旦引用一个实体,再不能引用其他实体。有人可能会问,为什么不可以引用别的实体呢?下面这个代码不就是引用了别的实体吗?

int main()
{
	int a = 10;
	int b = 20;
	int& ra = a;
	ra = b;
	return 0;
}

这里的“int& ra = a”当然不是引用别的实体,而是把a的值改成了b的值,大家不能把引用看作成指针指针指向的是地址,而指向的地址是可以随意改变的,因为指针并没有和某个地址绑定在了一起,而引用不一样,引用在定义的时候就已经和变量绑定在了一起。

三、常引用

引用和赋值和指针一样,权限可以缩小或平移,但不能放大。

若非得给a取别名,当然也有办法,那就是将b也修饰为常变量,这样b就也无法改变a的值了。

四、使用场景

1、做参数:

像在C语言中非常常见的交换变量值函数,为了通过函数交换两个变量的值,就必须将两个变量的地址传给函数,函数再将这两个变量解引用再进行交换,这样的话效率会很低下,但在C++中我们学了引用后,就可以非常轻松地交换两个变量的值,下面我用异或法交换两个变量的值:

void Swap(int& a, int& b)//异或法交换值
{
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
}
int main()
{
	int a = 10, b = 20;
	cout << "before exchaneging: " << "a:" << a << " " << "b:" << b << endl;
	Swap(a, b);
	cout << "after exchaneging:  " << "a:" << a << " " << "b:" << b << endl;
	return 0;
}

输出结果:

通过引用交换两个变量的值,大大提高了编程效率,当然,像一些在C语言中需要用到二级指针的函数,大多都是因为要改变一级指针的值,因此需要通过解引用一级指针的地址。但在学了引用后,这些二级指针都可以写成引用一级指针的方式。

2、做返回值:

在讲传引用做返回值前,首先来看一下这两个例子:

example 1:

int count()
{
	int i = 0;
	i++;
	return i;
}
int main()
{
	int a = count();
	cout << a;
	return 0;
}

在这个例子中,count()函数在返回i的时候会将i拷贝到一份临时变量中去,然后将临时变量赋值给a,因为该函数在运行完后函数栈帧会销毁,为了将i的值保留下来,不得不将i的值拷贝到临时变量中去。

example 2:

int count()
{
	static int i = 0;
	i++;
	return i;
}
int main()
{
	int a = count();
	cout << a;
	return 0;
}

这个例子中cout()函数中的i被存放在了静态区中,因此函数栈帧销毁并不会导致i的值被销毁,故我们只需要将i的值传给a即可。但计算机并不会因此直接将i的值传给a,而是和example 1一样拷贝一份临时变量,那么,我们如何才能直接将i的值传给a呢?这时候,我们就要用到引用做返回值了,我们只需要在函数名前面加一个&即可:

int& count()
{
	static int i = 0;
	i++;
	return i;
}
int main()
{
	int a = count();
	cout << a;
	return 0;
}

这样就能通过i的别名将值直接传给a,进一步降低了运行时间和空间。

除了static静态变量的值可以传引用返回,一些像动态内存开辟之类的出函数不会被销毁的变量作返回值时同样可以用传引用返回,但是如果变量出作用域就会被销毁就不能使用引用返回。同时,一些像类之类的知识中也会用到传引用返回,涉及后面知识的内容这里就不做深究了。

如果有什么别的疑问欢迎在评论区留言哦!

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘家炫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值