C++中“非常量引用的初始值必须是左值”的处理方法

原文:https://blog.csdn.net/hou09tian/article/details/80565343 

1 左值和右值
在C++中,左值可以出现在赋值语句的左边和右边;右值只能出现在赋值语句的右边,不能出现在赋值语句的左边。变量是左值,常量是右值。

2 引用
引用(reference)为对象起了另外一个名字,引用类型引用(refers to)另外一种类型。通过在变量名前添加“&”符号来定义。引用具体的使用方法请参考《C++的引用与重载函数》。

3 非常量引用的初始值必须是左值
3.1 产生原因
自定义函数increment()的代码为

void increment(double& x)
 
{
 
x += 1.0;
 
}

在调用该函数时,有如下代码

increment(5);

因为increment()函数的形参是double&,而调用时的实参是整形常量。因此,在调用increment()函数时实际上存在一个隐式的类型转换

double& temp = (double)5;
 
x = temp;

假设此后在increment()中对形参x进行修改,实际上就是对常量进行了修改,这显然是不能允许的。所以,在对非常量进行初始化时,该初始值必须是左值,而不能是右值。因此,会显示“非常量引用的初始值必须是左值”的错误信息。

3.2 解决方法
有两种方法可以解决以上问题,一是避免隐式转换;二是避免修改形参。

3.2.1 避免隐式转换
可以使用如下方法避免隐式转换

double i = 5.0l;
 
increment(i);

避免了隐式转换,也就是避免了对非常量引用的初始化。

3.2.2 避免修改形参
将increment()函数的形参类型修改为const double&,则在进行隐式转换时就可以用常量(右值)对其进行初始化了。

void increment(const double& x)
 
{
 
}

需要注意的时,因为此时形参x的值是常量,所以在increment()函数内部中不能对其进行修改。

4 实战
在CSDN论坛中有朋友提到如下问题

定义了一个Time类,重载cout输出time类时报错,其报错的信息即为“非常量引用的初始值必须是左值”。


ostream &  operator <<(ostream& os,Time& _t)
{
os<<_t.hour<<':'<<_t.minute<<':'<<_t.second<<endl;
 
return& os;
}


在《C++函数的返回值(上)》“当函数的返回值是非引用变量时,会用一个临时变量来保存该返回值;当函数的返回值是引用变量时,不使用临时变量,直接返回该引用”。
因为其重载的<<操作符的返回值是一个引用变量,因此不存在“3 非常量引用的初始值必须是左值”中提到的临时变量隐式转换的问题。该操作符return的是&os,其含义是os的地址,该地址是一个常量,即右值;而操作符返回值是一个非常量的引用,因此会产生“非常量引用的初始值必须是左值”的报错信息。

修改的方法为将重载的<<操作符的return改为

return os;

即可。


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值