引用及const引用

非const引用的类型必须要和所引用的对象类型一致;但const引用有两种例外:

1.允许用任意表达式作为初始值,只要该表达式能转换成引用的类型

int i = 42;
const int &r1 = i;		//√ 允许const int绑定到一个普通int对象上
const int &r2 = 42;		//√ r2是一个常量引用
const int &r3 = r1 * 2;	//√ r3是一个常量引用
int &r4 = r1 * 2;		//× r4是一个普通的非常量引用,非常量引用初始值必须为左值
int &r5 = 2;			//× 非常量引用初始值必须为左值

2.允许用任意类型对象作为初始值,前提是该类型对象能转换成引用的类型
究其根本原因:非常量引用的初始值必须为左值,常量引用的初始值可以为左值、右值。const引用初始化时,转换成引用类型的对象实为右值。

int i = 2;
double &r = i;		//编译报错
const double &r = i; //编译通过
//难道这个i不是左值?转换后确实不是

double i = 2;
double &r = i;		//编译通过
//难道这里的i又是左值了?

为什么会出现这种情况?先来看一个简单的例子

double dval = 0.114514;
const int &ri = dval;
cout << "ri = " << ri << endl;

//运行输出:
ri = 0

在这个过程中,由于类型不匹配,编译器把代码改成了:

double dval = 0.114514;
const int temp = dval;
const int &ri = temp;
cout << "ri = " << ri << endl;

这种情况下,ri绑定了一个临时量对象,临时变量都是const,所以没有const的引用会失败
你可以想象以下,如果ri不是常量时,执行了上述初始化过程会带来怎样的后果:
如果ri不是常量。就允许对ri赋值,这样就会改变ri所引用对象的值(此时绑定的是临时变量而非dval),所以C++也把以下这种行为归为非法

double dval = 0.114514;
int &ri = dval;//编译报错
cout << "ri = " << ri << endl;

同时注意,对const的引用可能引用一个并非const的对象

对const的引用仅对引用可参与的操作做出了限定,对于引用对象本身是否是一个常量没有做出限定,因此对象也可能是个非常量,允许通过其他途径改变它的值

int i = 42;
int &r1 = i;
const int &r2 = i;
//r2 = 0; //× r2是一个常量引用
cout << "r2 = " << r2 << endl;
r2 = 0;	//不可通过编译
i = 0;	//可通过编译
cout << "r2 = " << r2 << endl;

程序输出:
r2 = 42
r2 = 0

 

 
喜欢 0
分享