2016-05-14 82 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