对于这一个问题,我们要思考一下,重载=
到底意味着什么。下图代码中我首先是定义了一个void返回值的重载函数,运行代码,结果很正常,void应该是可以的。事实真的如此吗?
这里表面是重载赋值运算符,其实和setter方法没什么两样。我们需要考虑的是没有返回值类型就意味着,我们不能连续调用,即形如t3 = t2 = t1
是会出错的,我们作为程序的开发者,我们当然可以避免这种操作,但是既然是面向对象,那么我们就要避免这种行为,提高程序的鲁棒性。
重新回到t3 = t2 = t1
这里,注意=
是右结合,即t3 = (t2 = t1)
。为了实现"连锁赋值",赋值运算符必须返回一个指向操作符的左侧实参的引用。当然了返回Test值貌似也是可以的,但是我们需要注意会有额外的开销,包括匿名对象的拷贝构造函数和析构函数,当我们没有提供显式的拷贝构造函数时,匿名对象赋值给一个实例可能会出错,错误的原因就在于默认的拷贝构造函数是将类中的值完全的复制,当涉及到指针的时候,由于仅仅是浅拷贝,会在匿名对象被析构之后,指针会变成空悬指针。
#include<iostream>
#include<string>
using namespace std;
class TestA {
public:
TestA() { m_a = 0; m_b = 0; }
TestA(int a, int b) { m_a = a; m_b = b; }
/*void operator=(const TestA& tt) {
this->m_a = tt.m_a;
this->m_b = tt.m_b;
}*/
TestA& operator=(const TestA& tt) {
this->m_a = tt.m_a;
this->m_b = tt.m_b;
return *this;
}
void printA() { cout << m_a << " " << m_b << endl; }
private:
int m_a;
int m_b;
};
int main() {
TestA t1(3, 4);
TestA t2(4, 5);
TestA t3;
t3 = t2 = t1;
t2.printA();
t3.printA();
return 0;
}
输出如下,调用返回值为引用的赋值运算符重载函数,结果是符合预期的。
3 4
3 4