无法从“int *”转换为“int *&”?详解C++引用(&)使用方法

前言:无法从“int *”转换为“int *&”?

现在我想做下面这样的运算:

int i = 2;
int* &rp = &i;

结果是VS2013编译器报错,显示:无法从“int *”转换为“int *&”。
然后我定义一个指针p,指向i:int *p = &i;
结果是int * &rp = p;并不报错。

为什么会这样呢,按理说p和&i都是int*,为什么一个可以,一个不可以呢?答案就是&i是一个表达式的结果,而引用有一条规则是**引用只能绑定在对象上,不能与字面值或某个表达式的计算结果绑定在一起**。

同样的情况,当我们在给参数列表为int* &的函数传参时,也要注意这条,如下:

void fun(int* & rp)
{
	rp = new int(2);
}

int main()
{
	int a = 9;
	int *p = &a;

	fun(p);//正确,修改后*p = 2
	fun(&a);//错误,无法从“int *”转换为“int *&”
	return 0;
}

下面我将详细介绍引用(&)的用法,相信看完之后会对你有很大的帮助。

一.对普通变量的引用

所谓引用,就是给对象起另外一个名字。通常将引用的声明写成&d的形式来定义引用类型,其中d是声明的变量名。如int i = 20;int &d =i;就是定义i的引用,声明的变量名为d。

int ival = 1024;
int &refVal = ival;//refVal和ival绑定,是ival的另一个名字
//int &refVal2;//错误,引用必须被初始化

int &refVal3 = refVal;//可以多重绑定

上述中,ival、refVal和refVal3完全等价。可以用其任意一个给另外的整型变量赋值;给3个中的任意一个赋值,3个值都改变。说白了,这3个对应的是一块内存。

除此之外,定义引用可以在一条语句中:

int i = 1024,i2 = 2048;//i和i2都是int
int &r = i, r2 = i2;//r为引用,和i绑定;r2是int型

现在请判断如下定义是否合法:

int &refVal4 = 10;
double dval = 3.14;
int &refVal5 = dval;

第一个错误,因为引用的初始值必须是一个对象
第二个是正常定义,第三个错误,因为此处引用的类型的初始值必须是int型对象。

总结引用&使用规则

好了,到了这里,我们可以总结一下使用引用的一些限制:

  1. 引用必须初始化;
  2. 所有引用的类型都要和与之绑定的对象一致;
  3. 引用只能绑定在对象上,不能与字面值或某个表达式的计算结果绑定在一起

二.const的引用

在上一小结中,我们总结使用应用必须注意的3点。其实,对于第2点,有两个例外:

  • 例外1:int i = 42; const int & r = i*2;//正确,初始化常量引用时,可以不用与绑定的对象一致,允许使用任意表达式作为初值,只要表达式的结果能转换成引用的类型。同时对于第3点,也允许为一个常量引用(const 引用)绑定非常量的对象、字面值,甚至是表达式。如const int & r = 56;
  • 例外2:可以将基类的引用绑定到派生类对象上

对于例外2,这里暂不做讨论。关键是要理解例外1,这里用到了const,必须要注意“表达式的结果能转换成引用的类型”要求,如果转换不成引用的类型,是不能使用的。如,

double dval = 3.14;
const int &refVal5 = dval;

dval可以转换为int型,所以上述引用合法。如果是const string &r = dval;由于double无法转换为string类,所以会报错。

关于const的引用,可以参考我之前的文章详解const引用和常量指针、指向常量的指针,里面有一小节有详细介绍。

三.对指针的引用

直接看下面的例子:


int i = 1;
int *p = &i;//正确:&i为int*类型,p也为int *类型

int* &rp = p;//正确:rp与要绑定的p的类型严格匹配
int* &rp2 = &i;//错误:不满足引用限制的第3条。&i不是一个左值

要想让最后一个定义为正确,可以使用const,利用前面的例外1。如下,这样定义的引用是正确的。

int* const  &rp3 = &i;

这里提一个问题:&i是一个非常量地址,既能转换为常量指针int* const,也能转换为指向常量的指针const int*,那为什么使用前者,而后者不行呢?

简单点讲,指针的常量引用引用的是指针本身,所以应该是指针本身是个常量,而不是指针所指的内容是常量。
复杂点说,const引用非const对象时,会生成一个临时变量,非const对象赋值给这个临时变量,此时const引用引用的是这个临时变量。当使用const int*时,如 const int*&rp3 = &i;rp3可以改变指向,但是却无法改变被引用的非const对象&i的指向,因为rp3引用的是临时变量,这和引用的绑定含义违背,所以C++把其定义为非法。

再看下面的例子:

const int ci = 10;
const int *pc = &ci;// 正确:对常量取地址,总是看成底层const,即指向常量的指针

const int* &rpc = pc;//正确,rpc与要绑定的pc的类型严格匹配

要想引用&ci,由于它为表达式的结果,所以需要使用const,利用前面的例外1。由于&ci本身就为底层的const指针,加上指针要转化为常量指针,所以要像引用ci,必须用指向常量的常量指针:

const int* const &rpc3 = &ci;

四.总结引用:

使用引用时,其实很简单,把握住引用的几条规则即可

  1. 引用必须初始化;
  2. 所有引用的类型都要和与之绑定的对象一致;
  3. 引用只能绑定在对象上,不能与字面值或某个表达式的计算结果绑定在一起;
  4. 对于第2条,若是引用的类型和与之绑定的类型不一致,可以借用const,前提是与之绑定的类型要能转换为引用的类型
  5. 对于第3条,若就是想绑定字面值或表达式的计算结果,必须借用const

除此之外,还需明白:int* 是无法转换为const int *&的

五.2020/3/1更新:函数传参传引用或const引用

  1. 传引用需要和传值放在一起来讲的,区别不用多说,引用底层实现就是指针嘛!这个想必大家都懂。
  2. 对于传const引用的用处:第一是函数不能改变我传入参数的值;第二是可以向函数传入表达式的值或者字面值,这点可参考文章前面的第二节。

以上就是C++引用&的详细介绍。如果有疑问,欢迎评论区下方留言;本人水平有限 ,如有错误,也欢迎在评论区下方批评指正。若是喜欢本文,就帮忙点赞吧!

  • 13
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值