一、const与引用&定义和初始化
1、用数值常量初始化常量引用
1.1测试程序
int main(void)
{
const int& ra = 12;
cout<<"ra的值为:"<<ra<<endl
<<"ra的地址为:"<<&ra<<endl;
return 0;
}
1.2运行结果
1.3现象
可以用常量初始化一个const引用,并且产生了临时对象。
1.4结论
用常量初始化一个const引用,引用ra是编译器隐式创建的int型匿名对象的别名。
2、用相关类型变量初始化常量引用
类型相关:如果两个类型可以相互转换,则称这两个类型相关,只有相关类型之间才可以进行隐式或显式类型转换。
2.1测试程序
int main(void)
{
short a = 1;
const int& ra = a;
a = 2;
cout<<"a的值为:"<<a<<endl
<<"ra的值为:"<<ra<<endl
<<"a的地址为:"<<&a<<endl
<<"ra的地址为:"<<&ra<<endl;
return 0;
}
2.2运行结果
2.3现象
(1)a的值改变后,ra的值并没有改变;
(2)ra的内存地址和a的内存地址不一样;
2.4结论
ra并不是a的一个别名,编译器把short型数据转换成int型的匿名临时对象,ra是这个匿名临时对象的别名。
3、用相同类型变量初始化常量引用
3.1测试程序
int main(void)
{
int a = 1;
const int& ra = a;
a = 2;
// ra = 3; //Error:表达式必须是可修改的左值
cout<<"a的值为:"<<a<<endl
<<"ra的值为:"<<ra<<endl
<<"a的地址为:"<<&a<<endl
<<"ra的地址为:"<<&ra<<endl;
return 0;
}
3.2运行结果
3.3现象
(1)a的值改变时,ra的值也会跟着改变;
(2)ra的内存地址和a是一样的;
(3)试图用ra = 3;修改ra的值是非法的;
3.4结论
(1)ra就是变量a的一个别名;
(2)ra前面的const的修饰符的意思是不能通过ra修改ra所标识的那块内存区域,但却可以通过a来修改,这和常量指针类似;
二、const与引用&作为函数形参
1、形参为非常量引用,实参为同类型变量
1.1测试程序
int add2(int& a)
{
cout<<"add2函数中a的地址为:"<<&a<<endl;
int c = a + 2;
return c;
}
int main(void)
{
int x = 1;
cout<<"main函数中x的地址为:"<<&x<<endl;
add2(x);
// add2(4); //Error:非常量引用的初始值必须为左值
return 0;
}
1.2运行结果
1.3现象
(1)当实参为变量时,x和a的地址是一样的;
(2)当实参为常量时,编译器报错;
1.4结论
(1)当实参为变量时,形参就是实参的别名,占用同一块内存;
(2)当实参为常量时,编译器报错,这是因为不可以用const对象初始化非const引用;
2、形参为常量引用,实参为同类型变量和常量
2.1测试程序
int add2(const int& a)
{
cout<<"add2函数中a的地址为:"<<&a<<endl;
int c = a + 2;
return c;
}
int main(void)
{
int x = 1;
cout<<"main函数中x的地址为:"<<&x<<endl;
add2(x);
// add2(4); //可以通过编译
return 0;
}
2.2运行结果
2.3现象
(1)形参改为const引用后,传入常量时不会报错;
2.4结论
(1)传入常量时不会报错,因为可以用const对象初始化const引用,这时编译器会产生匿名临时对象,这就是上面介绍的用数值常量初始化常量引用。
3、形参为常量引用,实参为相关类型变量
3.1测试程序
int add2(const int& a)
{
cout<<"add2函数中a的地址为:"<<&a<<endl;
int c = a + 2;
return c;
}
int main(void)
{
short x = 1;
cout<<"main函数中x的地址为:"<<&x<<endl;
add2(x);
return 0;
}
3.2运行结果
3.3现象
(1)a的地址和x的地址并不一样;
3.4结论
(2)函数调用时对实参x进行了隐式类型转换,而且产生了临时对象,形参a是这个临时对象的别名;
三、关于常量引用型形参的几点总结:
1、为何要把形参声明成 const int & a形式
1.1、形参为 int& a,可不进行变量拷贝,节省内存,提高效率,但这种形参不允许传入像3这样的常量,所以要把形参声明为const int & a;
2、把形参声明为const int & a的优点:
2.1、a是实参的一个别名,没有进行内存拷贝,节省内存空间,提高了程序运行效率;
2.2、const修饰符可保证传入的实参在函数体内部不会被修改,如果形参是一个类对象的const&,则这个引用只能调用这个类的const成员函数,提高了程序的安全性;
2.3、使用const修饰符后,允许给函数传入常量,改善了程序的兼容性;
3、把形参声明为const int & a存在的问题:
3.1、传入常量时会伴随着临时对象的产生;
3.2、传入不匹配类型时(可隐式转换)会伴随着临时对象的产生;
参考资料:
[1] 刘光. 编码的法则:C++程序员不可不知的101条实用经验[M]. 北京:中国铁道出版社,2014. 39-42,85-89.
[2] http://blog.csdn.net/kevinzhangyang/article/details/6638479