C++引用reference

引用实际上是指针的一个扩展,引用最主要的特点是:它是一个虚拟的变量,不产生新的变量,只是引用其它已存在的变量,它只存在于我们的源码之中,不占有内存,引用实际上是变量的别名,所以对引用的改动实际上就是对目标的改动。

首先来举一个引用的例子:

#include<iostream>
#define LOG(x)  std::cout << x << std::endl

int main()
{
	int var = 6;
	int& ref = var;
	ref = 2;
	LOG(var);
	std::cin.get();
}

引用的格式:int& ref = var;。这里&读作引用,引用不能空引用,引用的变量前面也不用加什么奇奇怪怪的符号,但是后面必须要加上要引用的东西,如果是int& ref;这种形式而后面不接引用的变量,这样是错误的。
在这里,我们就创建了一个新的“别名”ref,因为这个ref不能称作是一个变量,如果你现在编译,它不会产生两个变量ref和var,只会产生一个var。现在我们可以做的是,由于ref已经引用了var,我们就可以通过ref来改变var的值。运行之后,输出结果为2,也就是var的值被改为了2。
ref就是a,我们只是给a起了一个别名。

来点高级的,假如我们现在想写一个函数,使得这个函数能够让输入整数递增。

#include<iostream>
#define LOG(x)  std::cout << x << std::endl

void add(int value)
{
	value++;
}
int main()
{
	int var = 6;
	add(var);
	LOG(var);
	std::cin.get();
}

运行之后的结果,var依然为6,没有发生加一递增,why?
传值操作,这里产生了一个新变量value,相当于开始先把var的值传给了value,然后通过add函数后value的值变为了7,而var的值并没有改变

既然变量var的值实际上并没有改变,那要想变量传递进函数并改变变量var的值,可以怎么做呢?
我们可以不把值传递进函数,而是把地址传递进函数。这里就要用到指针

#include<iostream>
#define LOG(x)  std::cout << x << std::endl


void add(int* value)
{
	(*value)++;
}
int main()
{
	int var = 6;
	add(&var);
	LOG(var);
	std::cin.get();
}

注意:(*value)++;一句中,由于自增操作符的优先级要比解引用的优先级要高,我们要加括号来保证先进行解引用在对其进行自增,否则的话是地址先加一然后再解引用,而var地址内的值并没有改变。

上面是用指针的方法改变var的值,我们还可以用引用的方式将代码变得更为简洁一点:

#include<iostream>
#define LOG(x)  std::cout << x << std::endl

void add(int& value)
{
	value++;
}
int main()
{
	int var = 6;
	add(var);
	LOG(var);
	std::cin.get();
}

传值操作时,由于产生了一个新的变量value,所以进行加一操作的实际上是value而不是var。但是现在进行了引用,正如最开始时的说明,引用实际上不产生新的变量,只是对已存在的变量进行引用,所以这里value就是var,我们在函数中改变了value的值,实际上也就是改变了var的值。
同时再注意一下格式:把函数中的形参定义由指针改成引用的格式,这样做的好处就是:引用之后,我们就是对var这个值进行操作了,所以函数中的value++前也不用再加上*解引用了;同时引用时时也不用再用var的地址进行传递了,直接用var进行传递。
运行结果如图所示:
在这里插入图片描述
var=7,我们成功对var的值进行了修改,和用指针对地址进行传递是相同的。

还需要注意的一点是,一旦你声明了一个引用就不能更改它引用的对象。举例:

int a = 2;
int b = 6;
int& ref = a;
ref = b;

这样操作是完全不行的,这里发生的是把b的值赋给了a的引用,输出为a=8,b=8。所以如果我们真的想改变ref所指代的是什么的时候,该怎么做呢?
我们需要创建一些变量使得它先指向a,再指向b,我们创建一个指针来完成。

#include<iostream>
#define LOG(x)  std::cout << x << std::endl

void add(int& value)
{
	value++;
}
int main()
{
	int a = 5;
	int b = 8;

	int* ref = &a;
	*ref = 2;
	ref = &b;
	*ref = 3;
	LOG(a);
	LOG(b);
	std::cin.get();
}

输出结果为:

a的值为2,b的值为3,这样我们就使用指针使得ref先指向a又指向了b,并且通过解引用修改了变量的值。

指针和引用的区别

由上面我们可以看出,指针和引用有相似之处,他们的区别到底是什么呢?

  1. 在任何情况下,都不能使用指向空值的引用。也就是说存在空指针,但是不存在空引用。
  2. 使用引用之前不需要测试它的合法性,相反,指针应该总是被测试,以防止它为空,这是因为引用在声明时就已经指定了对象,且会一直指向对象,因此无需做合法性测试。
  3. 指针可以被重新赋值以指向另一个不同的对象,但是引用总是指向在初始化被指定的对象,以后不能改变。

与按值传递不同,引用传递不再生成参数的一个数值副本,取而代之的是被调函数收到了一个引用,这个引用指向了主调函数的真实参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值