美文网首页
C++ move构造函数和move赋值

C++ move构造函数和move赋值

作者: Little熊猫 | 来源:发表于2018-09-07 17:07 被阅读0次

    看一下下面这个例子

    template<class T>
    class Auto_ptr3
    {
        T* m_ptr;
    public:
        Auto_ptr3(T* ptr = nullptr)
            :m_ptr(ptr)
        {
        }
     
        ~Auto_ptr3()
        {
            delete m_ptr;
        }
     
        // Copy constructor
        // Do deep copy of a.m_ptr to m_ptr
        Auto_ptr3(const Auto_ptr3& a)
        {
            m_ptr = new T;
            *m_ptr = *a.m_ptr;
        }
     
        // Copy assignment
        // Do deep copy of a.m_ptr to m_ptr
        Auto_ptr3& operator=(const Auto_ptr3& a)
        {
            // Self-assignment detection
            if (&a == this)
                return *this;
     
            // Release any resource we're holding
            delete m_ptr;
     
            // Copy the resource
            m_ptr = new T;
            *m_ptr = *a.m_ptr;
     
            return *this;
        }
     
        T& operator*() const { return *m_ptr; }
        T* operator->() const { return m_ptr; }
        bool isNull() const { return m_ptr == nullptr; }
    };
     
    class Resource
    {
    public:
        Resource() { std::cout << "Resource acquired\n"; }
        ~Resource() { std::cout << "Resource destroyed\n"; }
    };
     
    Auto_ptr3<Resource> generateResource()
    {
        Auto_ptr3<Resource> res(new Resource);
        return res; // this return value will invoke the copy constructor
    }
     
    int main()
    {
        Auto_ptr3<Resource> mainres;
        mainres = generateResource(); // this assignment will invoke the copy assignment
     
        return 0;
    }
    

    输出:

    Resource acquired
    Resource acquired
    Resource destroyed
    Resource acquired
    Resource destroyed
    Resource destroyed
    

    好多构造函数和析构函数执行,下面分析一下每个打印代表的步骤
    1)nside generateResource() new Resource构造函数调用
    2)generateResource 返回main,res调用copy构造函数给一个临时变量

    1. res在generateResource退出后调用析构函数
      4)临时变量调用copy构造函数给mainres
    2. 临时变量调用析构函数
    3. main退出,mainres 调用析构函数
      优化如下:
    #include <iostream>
     
    template<class T>
    class Auto_ptr4
    {
        T* m_ptr;
    public:
        Auto_ptr4(T* ptr = nullptr)
            :m_ptr(ptr)
        {
        }
     
        ~Auto_ptr4()
        {
            delete m_ptr;
        }
     
        // Copy constructor
        // Do deep copy of a.m_ptr to m_ptr
        Auto_ptr4(const Auto_ptr4& a)
        {
            m_ptr = new T;
            *m_ptr = *a.m_ptr;
        }
     
        // Move constructor
        // Transfer ownership of a.m_ptr to m_ptr
        Auto_ptr4(Auto_ptr4&& a)
            : m_ptr(a.m_ptr)
        {
            a.m_ptr = nullptr; // we'll talk more about this line below
        }
     
        // Copy assignment
        // Do deep copy of a.m_ptr to m_ptr
        Auto_ptr4& operator=(const Auto_ptr4& a)
        {
            // Self-assignment detection
            if (&a == this)
                return *this;
     
            // Release any resource we're holding
            delete m_ptr;
     
            // Copy the resource
            m_ptr = new T;
            *m_ptr = *a.m_ptr;
     
            return *this;
        }
     
        // Move assignment
        // Transfer ownership of a.m_ptr to m_ptr
        Auto_ptr4& operator=(Auto_ptr4&& a)
        {
            // Self-assignment detection
            if (&a == this)
                return *this;
     
            // Release any resource we're holding
            delete m_ptr;
     
            // Transfer ownership of a.m_ptr to m_ptr
            m_ptr = a.m_ptr;
            a.m_ptr = nullptr; // we'll talk more about this line below
     
            return *this;
        }
     
        T& operator*() const { return *m_ptr; }
        T* operator->() const { return m_ptr; }
        bool isNull() const { return m_ptr == nullptr; }
    };
     
    class Resource
    {
    public:
        Resource() { std::cout << "Resource acquired\n"; }
        ~Resource() { std::cout << "Resource destroyed\n"; }
    };
     
    Auto_ptr4<Resource> generateResource()
    {
        Auto_ptr4<Resource> res(new Resource);
        return res; // this return value will invoke the move constructor
    }
     
    int main()
    {
        Auto_ptr4<Resource> mainres;
        mainres = generateResource(); // this assignment will invoke the move assignment
     
        return 0;
    }
    

    输出:

    Resource acquired
    Resource destroyed
    

    1)第一步同上
    2)函数返回,保存返回值给临时变量,调用move constructed函数,只进行指针copy
    3)函数返回,res回收,由于res不指向任何值,因此没操作
    4)临时变量赋值给mainres,同第2不
    5)main退出,临时变量不指向任何值,无操作
    6)main退出,mainres 调用析构函数"Resource destroyed"执行

    那么什么条件下执行copy构造函数,什么情况下调用Move构造函数
    1) 如果我们给一个l-value赋值的时候,调用copy构造函数
    2)如果给一个r-value赋值的时候,调用Move构造函数,因为r-value都是临时的,将要被销毁的
    在上面的例子中,generateResource()函数返回值调用的是move构造函数,而不是copy构造函数,跟第一条不符?C++定义函数返回值是调用move即使是给l-value复制。

    相关文章

      网友评论

          本文标题:C++ move构造函数和move赋值

          本文链接:https://www.haomeiwen.com/subject/nkncgftx.html