copying 函数

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;
}

猜你喜欢

转载自blog.csdn.net/u011857683/article/details/81436300