1、引用的基本作用是给变量起别名;
2、引用必须初始化,引用在初始化后,不可以改变;
3、函数传参时,(形参是对象时,不会调用拷贝构造)且可通过形参修改实参;
4、引用的本质在c++内部实现是一个指针常量。
在运算符重载时,允许进行连续赋值,如连续赋值 = += -= *= 、=,<<输出流,需要返回引用对象。
一、返回对象与返回对象引用的区别
1、返回对象
class MyString
{
public:
.....
MyString operator=(cosnt Widget& rhs)
{
...
return* this;
}
};
返回对象时,系统会调用拷贝构造,构造一个匿名的对象作为返回。
当s1=s2=s3时,赋值流程为:
先s2=s3,使得s2的值等于s3;
接着在return *this时,拷贝构造s2,生成一个匿名对象;
最后s1 = 匿名对象,匿名对象析构。
最终实现效果为s1、s2、s3都相等
当(s1=s2)=s3时,赋值流程为:
先s1=s2,使得s1的值等于s2;
接着在return *this时,拷贝构造s1,生成一个匿名对象;
最后 匿名对象 = s3,匿名对象析构。
最终实现效果为s1、s2相等,但s1=s3的赋值无法实现,
所以(s1=s2)=s3不成功。
2、返回对象引用
class MyString
{
public:
.....
MyString& operator=(cosnt Widget& rhs)
{
...
return* this;
}
};
返回对象引用时,系统不会调用拷贝构造,节省资源,提高程序运行效率。
当s1=s2=s3时,赋值流程为:
先s2=s3,使得s2的值等于s3;
接着return *this的引用,即s2的引用作为返回;
最后s1 = s2;
最终实现效果为s2先等于s3,s1再等于s2,
s1、s2、s3都相等
当(s1=s2)=s3时,赋值流程为:
先s1=s2,使得s1的值等于s2;
接着return *this的引用,即s1的引用作为返回;
最后 s1 = s3;
最终实现效果为s1先等于s2再等于s3。
二、加号的重载不能用返回引用对象(在重载等号深拷贝的情况下)
加号做返回对象引用时,无法实现s1=s1+s3
加法返回对象引用时
s1=s1+s3,赋值流程为:
s1+s3,return *this的引用,即加法计算后的s1;
接着s1 = s1时,由于重载等号且深拷贝会对this->str进行delete,再进行赋值,则此时的右值s1也受delte影响,导致最终s1->str是delete掉的野指针。