2016-05-14 62 views
1

我在看下面的例子就移動構造函數/賦值: https://msdn.microsoft.com/en-us/library/dd293665.aspx爲什麼拷貝構造函數choosen搬過來contrstructor

我已經加入了交換功能,以簡化移動構造函數/分配和修改了一些拷貝賦值:

#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. 

(構造函數調用缺少這意味着移動構造函數被使用)

回答

4

許多矢量操作要求在拋出異常時沒有效果(強壯的異常保證)。強異常保證休息,如果移動構造函數可以拋出:

梗概爲push_back

導致重新分配,如果新的尺寸比舊款更大的容量。 如果沒有重新分配,插入點的所有迭代器和引用在 之前保持有效。如果複製構造函數拋出除 之外的異常,則移動構造函數,賦值運算符或的移動賦值運算符或任何InputIterator操作 都不會產生影響。如果在末尾插入 單個元素並且TCopyInsertableis_nothrow_move_constructible<T>::value爲真時引發異常,則沒有 影響。 否則,如果移動 非CopyInsertable T的構造函數引發異常,則效果未指定爲 。

由於TCopyInsertible,它使用拷貝構造函數,而不是移動構造函數。

+0

你大膽的錯了句子嗎?我認爲在加粗之前的句子與你答案的其餘部分更相關。雖然很好的答案。 – hvd

相關問題