1. 概念
引用就是给对象起了一个别名,引用并不是对象,它只是给一个已经存在的对象起了个另外的名字。同时,程序把引用和它的初始值绑定在一起,而不是拷贝给引用。你对引用对象的操作,即是对原对象的操作。
int a=10;
int &b=a;
★注意
- 引用必须被初始化。
- 引用本身不是对象,不能定义引用的引用。
- 一般来说引用的类型必须与其所引用的对象的类型一致,并且不能直接绑定字面值,但是有两个例外,常量引用和存在继承关系的类。
- 一般引用绑定只能是对象,而不能是字面值或某个表达式的结果。但是常量引用和存在继承关系的类仍然例外。
2. 常量引用
定义
把引用绑定到const对象上,就像绑定到其他对象上一样,称之为对常量的引用,常量的引用不能被用作修改它所绑定的对象,即常量引用绑定了的对象将不能再进行修改。常量引用的作用一般是用来给对象取别名的和存储一个变量的初始值。
int a=10;
const int &b=a;
b=20;//错误
常量引用可以不必与其所引用对象的类型一致
如:
int i=10;
const int &r1=i;
const int &r2=20;
const int &r3=r1*2;
以上是正确的,此时,虽然左边是const int 类型的引用,而右边分别是int类型、字面值类型以及表达式,不与左边的常量引用类型相匹配,但是这也是正确的。对于表达式注意,这个表达式必须最终能转换为引用的类型。
如:
int &r4=r1*2;
这个就是错误的,因为左边是int类型的引用,并不是常量引用,所以它必须要与右边的类型相匹配。
发生细节
如一个常量引用:
double b=3.14;
const int &a=b;
这其中编译器做了一些事情
double b=3.14;
const int &a=b;
(
//编译器做的事
const int temp=b;
const int &a=temp;
//
)
这其中的temp成为临时量,临时量:编译器创建的一个空间来暂存表达式的求值结果时临时创建的一个未命名的对象。其实这也说明了,为什么非常量引用的两边类型要一致,而常量引用的两边类型可以不一致。
3. 非常量引用不能绑定临时数据,常量引用可以绑定临时数据(★★★)
class Sales_data
{
public:
Sales_data(std::string name){ }
private:
std::string book;
};
Sales_data & func(Sales_data &a)
{
return a;
}
int main()
{
std::string s;
func(s); // 在这里编译器会生成一个临时对象进行处理
} // Sales_data sd=s; //隐性转换,执行构造函数,sd(s); 生成一个临时对象sd
// Sales_data &a=sd; //将sd拷贝给a
// 报错!!!!!!!!!!!!因为非常量引用不能绑定临时变量
为什么非常量引用不能绑定临时数据?
因为:如果形参是非常量引用,那么编译器会认为在下面的程序中会修改这个临时数据,并且程序员需要获取这个临时数据,但由于临时数据的特殊性,即“临时性”,临时数据会很快被销毁,这样的话,在这个函数里对临时数据的操作就没有意义了,容易出现未知BUG。所以C++11不允许,非常量引用绑定到临时数据。
为什么常量引用可以绑定临时数据?
因为:常量引用绑定的临时量在下面的程序里是不能改变的,也就不存在无意义的操作了。