为什么要在operator=中返回"*this"的引用
副标题#e#
[问题的提出]:
在许多书籍和文章中,许多次提到在对赋值操纵符(=)举办重载的时候,要返回对目标(挪用)工具实例(*this)的引用。个中难免有这样的论断:必然要返回对换用工具的引用;返回对换用实例工具的引用是为了实现链式持续赋值。
这里说明两个问题:第一,是否重载赋值操纵符必需返回对换用工具的引用,第二,是否这样就可以实现链式赋值,而不这样就不可。
首先,必需认可,返回对"*this"的引用是尺度的二目操纵符重载的名目,效率很高。这样做有许多利益:如实现链式赋值、制止姑且工具的发生(挪用拷贝结构函数)、销毁(挪用析构函数),但不长短这样做不行,下面通过比拟来阐述返回对"*this"的引用的利益及其他做法的缺点,同时也能清楚第二个问题,我们从例子着手。
// a.h
class A
{
public:
A();
A(int nTest);
A(const A& a);
virtual ~A();
A operator=(const A& a);
// A& operator=(const A& a);
private:
int m_nTest;
public:
void printit();
};
}
// a.cpp
A::A(int nTest)
{
m_nTest = nTest;
cout << "constructor A Value is executed now!" << endl;
}
A::A(const A& a)
{
this->m_nTest = a.m_nTest;
cout << "Copy constructor A is executed now!" << endl;
}
A::A()
{
cout << "constructor A Default is executed now!" << endl;
}
A::~A()
{
cout << "Destructor A is executed now!" << endl;
}
A A::operator=(const A& a)
// A& A::operator=(const A& a)
{
if (this==&a)
return *this;
this->m_nTest = a.m_nTest;
cout << "Assignment A is
executed now!" << endl;
return *this;
}
#p#副标题#e#
在main()函数中挪用
A a(100),b(99),c(98);
a = b = c;
a.printit();
b.printit();
c.printit();
功效为:
constructor A Value is executed now!
constructor A Value is executed now!
constructor A Value is executed now!
Assignment A is executed now!
Copy constructor A is executed now!
Assignment A is executed now!
Copy constructor A is executed now!
Destructor A is executed now!
Destructor A is executed now!
99
99
98
Destructor A is executed now!
Destructor A is executed now!
Destructor A is executed now!
假如将 A operator=(const A& a) 改为 A& operator=(const A& a)
则功效为:
constructor A Value is executed now!
constructor A Value is executed now!
constructor A Value is executed now!
Assignment A is executed now!
Assignment A is executed now!
98
98
98
Destructor A is executed now!
Destructor A is executed now!
Destructor A is executed now!
两者的差异为前者比后者多执行了两次结构(拷贝结构函数)和析构函数,可见在执行进程充发生了两个姑且工具。
[1]在赋值函数为:A operator=(const A& a)的环境下
对付a=b=c; 实际为a.operator=(b.operator=(c))
在执行A operator=(const A& a) 后返回 *this 给一个姑且工具,所以生成和销毁这个姑且工具的时候别离要挪用结构和析构函数,而结构时是用一个已经存在的实例出初始化同范例的实例,所以挪用的拷贝初始化函数。析构时,先析构前面一个(a.operator=)发生的姑且工具,后析构"b.operator="发生的姑且工具.
[2] 在赋值函数为:A& operator=(const A& a)的环境下
差异的是没有姑且工具的发生,因为operator=返回的是对当前工具的引用,而引用只是别名,而不是结构新工具的。这点可以通过如下函数挪用来领略:
void fun(A& temp)
{
temp …
}
A a;
执行fun(a)函数挪用时,没有发生姑且工具。
可见,重载"="操纵符,不必然要返回对赋值目标工具的引用,但返回引用是很好的做法,发起您这样利用。
最后提出几个问题,各人可以思考一下:
[1] 若将a=b=c; 改为(a=b)=c后别离挪用A operator=(const A& a) 和A&operator=(const A& a)功效会有什么差异?
[2] 可否将A&operator=(const A& a)改为const A&operator=(const A& a)?
[3] 可否将A&operator=(const A& a)中的return *this;改为return a?
[4] A a, b;
a = b;
与 A a;
A b = a; 有什么差异?
程度有限,接待各人品评指正!
本文配套源码