1. 概述
copying函数包括copy构造函数和copy assignment 操作符。
2. copying函数注意事项
2.1 令operator= 返回一个 reference to *this
令operator= 返回一个 reference to *this,可以实现连续赋值。
x = y = z
2.2 在operator= 中处理“自我赋值”
当你重新定义copying函数,此时对象需要考虑资源释放时,那么在进行赋值操作时需要考虑“自我赋值”的情况。
确保当对象自我赋值时operator= 有良好行为。其中包括比较“来源对象”和“目标对象的地址”、精心周到的语句顺序、以及copy-and-swap。
问题代码:
#include <iostream>
using namespce std;
class TestOne
{
TestOne()
{
}
}
class TestTwo
{
TestTwo()
{
m_testOne = new TestOne();
}
~TestTwo()
{
detele m_testOne
}
TestTwo& operator=(const TestTwo& rhs)
{
//存在问题, 不仅不具备"自我赋值安全性",而且不具备"异常安全性"
delete m_testOne;
m_testOne = new TestOne(*rhs.m_testOne);
return *this;
}
private:
TestOne* m_testOne;
}
(1) 证同测试
具备"自我赋值安全性",不具备"异常安全性",如果new出现异常,m_testOne最终指向一块被删除的内存。
TestTwo& operator=(const TestTwo& rhs)
{
//存在问题, 具备"自我赋值安全性",不具备"异常安全性"
if(this == &rhs)
{
return *this;
}
delete m_testOne;
m_testOne = new TestOne(*rhs.m_testOne);
return *this;
}
(2) 精心周到的语句顺序
TestTwo& operator=(const TestTwo& rhs)
{
//具备"自我赋值安全性"和"异常安全性"
TestOne* testOne = m_testOne;
m_testOne = new TestOne(*rhs.m_testOne);
delete m_testOne;
return *this;
}
2.3 复制对象时勿忘其每一个成分
(1) copying函数应该确保复制 “对象体内的所有成员变量” 及“所有基类成分”。
(2) 不要尝试以某个copying函数实现另外一个copying函数(即,不要尝试copy assignment 操作符和copy构造函数相互调用)。应该将共同机能放进第三个函数中,并由两个copying函数共同调用。
案例
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
}
Test(const Test& test):
m_a(test.m_a)
{
}
Test& operator=(const Test& rhs)
{
this->m_a = rhs.m_a;
//赋值返回引用
return *this;
}
private:
int m_a;
};
class TestTwo : public Test
{
public:
TestTwo()
{
}
TestTwo(const TestTwo& rhs):
Test(rhs),
m_b(rhs.m_b)
{
}
TestTwo& operator=(const TestTwo& rhs)
{
//调用基类赋值操作符,赋值操作符调用基类赋值操作符(不会去混用基类拷贝构造函数)
Test::operator=(rhs);
//本类成员赋值
m_b = rhs.m_b;
//赋值返回引用
return *this;
}
private:
int m_b;
};
int main()
{
Test test;
Test test2(test);
Test testTwo;
Test testTwo2(testTwo);
return 0;
}