const 引用

/**** code 1 ****/
#include <string>  
#include <iostream>  
using namespace std;  
int main()  
{    
	double val = 3.14;
	const double &ref1 = val;   //const double const *ref1 = &val;
	
	const int    &ref2 = val;   //int temp = val;  const int & ref2 = temp;
	
	double       &ref3 = val;
	
	int          &ref4 = val;  //cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
    /*这是因为,val是double类型,而ref4的形参是int类型,因此当val作为实参传给ref4时,会导致生成一个 临时的int变量,
假设为c,此时c为右值,将c绑定到非常量引用ref4是不被允许的,因为这改变了右值不可被修改的语义,容易产生莫名的bug。
而常量左值引用可以绑定到右值,因为这从语义上保证了不会改变右值。*/
	
	cout << "ref1 = " << ref1 << "    ref2 = " << ref2 << "    ref3 = " << ref3 << endl;     	//ref1 = 3.14    ref2 = 3    ref3 = 3.14
	
	val = 4.14;
	cout << "ref1 = " << ref1 << "    ref2 = " << ref2 << "    ref3 = " << ref3 << endl;	    //ref1 = 4.14    ref2 = 3    ref3 = 4.14
	
	
	double *p1 = (double *)&ref1;
	*p1 = 5.14;
	cout << "*p1 = " << *p1 << "    ref1 = " << ref1 << "    val = " << val <<endl;    //*p1 = 5.14    ref1 = 5.14    val = 5.14
	
	int *p2 = (int *)&ref2;
	*p2 = 6.14;
	cout << "*p2 = " << *p2 << "    ref2 = " << ref2 << "    val = " << val <<endl;    //*p2 = 6    ref2 = 6    val = 5.14
	
	
	//ref1 = 7.14;   //error: assignment of read-only reference 'ref1'
}

/**** code 2 ****/
void func(int& a)
{
    a++;
}

int main()
{
    double b = 1.2;
    func(b);
    return 0;
}
这是因为,b是double类型,而func的形参是int类型,因此当b作为实参传给func时,会导致生成一个临时的int变量,
假设为c,此时c为右值,将c绑定到非常量引用a是不被允许的,因为这改变了右值不可被修改的语义,容易产生莫名的bug。
而常量左值引用可以绑定到右值,因为这从语义上保证了不会改变右值。

如果一个参数是以非const引用传入,c++编译器就有理由认为程序员会在函数中修改这个值,并且这个被修改的引用在函数返回后要发挥作用。但如果你把一个临时变量当作非const引用参数传进来,由于临时变量的特殊性,程序员并不能操作临时变量,而且临时变量随时可能被释放掉,所以,一般说来,修改一个临时变量是毫无意义的,据此,c++编译器加入了临时变量不能作为非const引用的这个语义限制。



/**** const 引用 ****/
const引用是指向const对象的引用
const int val = 512;
const int &refval = val;//不能对const对象val修改,因此也不能通过引用refval来修改val
int &ref2 = val; // 错误,非const引用不能绑定const对象
const引用是绑定const对象的引用,非const引用是绑定非const对象的引用。

注意:const引用可以初始化为不同类型的对象或初始化为右值,如字面值常量:
int i = 42;
const int &r = 42; //正确
const int &r2 = r+i;//正确

同样的初始化对于非const引用却不合法,而且会导致编译错误。原因非常微妙:
double val = 3.14;
const int &r = dval;
编译器会把代码转换成如下的编码
int temp = dval; //创建一个新的变量
const int &r = tmp; //
如r不是const,那修改r不会修改dval,而是修改temp。期望修改r从而修改dval的程序员发现dval并没有修改
仅允许const引用绑定到临时使用的值完全避免这个问题,因为const引用是只读的。

非const引用只能绑定到该引用同类型的对象。
const引用则可以绑定到不同但相关的类型对象或绑定到右值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值