簡體   English   中英

為什么選擇復制構造函數而不是移動構造函數

[英]Why is copy constructor chosen over move constructor

我正在查看以下有關移動構造函數/分配的示例: https : //msdn.microsoft.com/zh-cn/library/dd293665.aspx

我通過添加交換函數來簡化移動構造函數/賦值和副本賦值進行了一些修改:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class MemoryBlock
{
public:

    // Simple constructor that initializes the resource.
    explicit MemoryBlock(size_t length)
        : _length(length)
        , _data(new int[length])
    {
        std::cout << "In MemoryBlock(size_t). length = "
                  << _length << "." << std::endl;
    }

    // Destructor.
    ~MemoryBlock()
    {
        std::cout << "In ~MemoryBlock(). length = "
                  << _length << ".";

        if (_data != nullptr)
        {
            std::cout << " Deleting resource.";
            // Delete the resource.
            delete[] _data;
        }

        std::cout << std::endl;
    }

    // Copy constructor.
    MemoryBlock(const MemoryBlock& other)
        : _length(other._length)
        , _data(new int[other._length])
    {
        std::cout << "In MemoryBlock(const MemoryBlock&). length = "
                  << other._length << ". Copying resource." << std::endl;

        std::copy(other._data, other._data + _length, _data);
    }

    // Copy assignment operator.
    MemoryBlock& operator=(MemoryBlock& other)
    {
        std::cout << "In operator=(const MemoryBlock&). length = "
                  << other._length << ". Copying resource." << std::endl;

        swap(*this, other);
        return *this;
    }

    // Retrieves the length of the data resource.
    size_t Length() const
    {
        return _length;
    }

    // Move constructor.
    MemoryBlock(MemoryBlock&& other)
        : _data(nullptr)
        , _length(0)
    {
        std::cout << "In MemoryBlock(MemoryBlock&&). length = "
                  << other._length << ". Moving resource." << std::endl;


        *this = std::move(other);
    }

    // Move assignment operator.
    MemoryBlock& operator=(MemoryBlock&& other)
    {
        std::cout << "In operator=(MemoryBlock&&). length = "
                  << other._length << "." << std::endl;

        swap(*this, other);
        return *this;
    }

    void swap(MemoryBlock& first, MemoryBlock& second)
    {
        using std::swap;
        swap(first._length, second._length);
        swap(first._data, second._data);
    }

private:
    size_t _length; // The length of the resource.
    int* _data; // The resource.
};

int main()
{
   // Create a vector object and add a few elements to it.
   vector<MemoryBlock> v;
   v.push_back(MemoryBlock(25));
   v.push_back(MemoryBlock(75));

   // Insert a new element into the second position of the vector.

   v.insert(v.begin() + 1, MemoryBlock(50));
}

現在,當我運行代碼時,將顯示以下輸出:

In MemoryBlock(size_t). length = 25.
In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.
In operator=(MemoryBlock&&). length = 25.
In ~MemoryBlock(). length = 0.
In MemoryBlock(size_t). length = 75.
In MemoryBlock(MemoryBlock&&). length = 75. Moving resource.
In operator=(MemoryBlock&&). length = 75.
In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(size_t). length = 50.
In MemoryBlock(MemoryBlock&&). length = 50. Moving resource.
In operator=(MemoryBlock&&). length = 50.
In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.
In MemoryBlock(const MemoryBlock&). length = 75. Copying resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.
In ~MemoryBlock(). length = 0.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.

我不明白為什么有時會在移動構造函數上調用復制構造函數?

如果刪除移動構造函數定義,並將其聲明為默認值:

// Move constructor.
MemoryBlock(MemoryBlock&& other) = default;

然后我得到正確的輸出:

In MemoryBlock(size_t). length = 25.
In ~MemoryBlock(). length = 25. Deleting resource.
In MemoryBlock(size_t). length = 75.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.
In MemoryBlock(size_t). length = 50.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.

(輸出中缺少構造函數調用,這意味着使用了move構造函數)

許多向量操作要求在引發異常時不起作用(強烈的異常保證)。 如果move構造函數可以拋出以下異常,則強異常保證會中斷:

push_back提要:

如果新大小大於舊容量,則導致重新分配。 如果沒有發生重新分配,則插入點之前的所有迭代器和引用均保持有效。 如果T的復制構造函數,移動構造函數,賦值運算符或移動賦值運算符或任何InputIterator操作引發了異常,則沒有任何效果。 如果在末尾插入單個元素時拋出異常,並且TCopyInsertableis_nothrow_move_constructible<T>::value為true,則沒有效果。 否則,如果非CopyInsertable T的move構造函數引發異常,則效果未指定。

由於T CopyInsertible ,所以它使用復制構造函數而不是move構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM