2017-07-03 61 views
3

我正在嘗試學習C++ 11中的新功能。我正在XCode中測試下面的代碼。爲什麼移動構造函數只有在矢量中已經存在元素時才被調用?

#include <iostream> 
#include <string> 
#include <vector> 

class CClass 
{ 
    std::string s; 
public: 
    CClass() 
    { 
     std::cout<<"Default Constructor"<<std::endl; 
    } 
    CClass(const std::string v) :s(v) { 
     std::cout<<"Constructor"<<std::endl; 
    } 

    CClass(const CClass& other): s(other.s) { 
     std::cout<<"Copy Constructor"<<std::endl; 
    } 
    CClass(CClass&& a) noexcept 
    { 
     std::cout<<"Move Constructor"<<std::endl; 
     s = std::move(a.s); 
    } 
    CClass& operator = (const CClass& other)noexcept 
    { 
     std::cout<<"Copy Assignment"<<std::endl; 
     if(this != &other) 
     { 
      s = other.s; 
     } 
     return *this; 
    } 
    CClass& operator = (CClass&& other) noexcept 
    { 
     std::cout<<"Move Assignment"<<std::endl; 
     if(this != &other) 
     { 
      s = std::move(other.s); 
     } 
     return *this; 
    } 
}; 

int main() 
{ 
    std::vector<CClass> v; 
    CClass x("hello"); 
    //v.push_back(x); 
    std::cout<<"--------------------"<<std::endl; 
    v.emplace_back("uiuiu"); 
    std::cout<<"--------------------"<<std::endl; 
} 

當我取消推回我得到以下結果:

Constructor 
Copy Constructor 
-------------------- 
Constructor 
Move Constructor 
-------------------- 

否則,如果我評論它,我得到:

Constructor 
-------------------- 
Constructor 
-------------------- 

我的問題是,爲什麼是移動構造函數不會在第二種情況下調用?它只在第一種情況下被稱爲矢量最初不爲空時。

回答

7

這是因爲矢量中的一個元素需要移動到新的內存位置。發生這種情況的原因是新尺寸會超出矢量容量,因此必須爲矢量分配具有新容量的新內存。

std::vector::emplace_back

如果新size()大於capacity()那麼所有迭代器和引用(包括過去的最末端迭代器)無效。否則只有最後一個迭代器失效。

由於相同的原因,迭代器和引用無效:因爲元素現在存儲在內存中的新位置。

如果在第一種情況下調用reserve,你會看到,沒有轉移構造函數被調用:

CClass x{"hello"}; // constructor 
v.reserve(2); // make space for 2 elements (you could have also used resize) 
v.push_back(x); // copy constructor 
v.emplace_back("uiuiu"); // constructor 
+0

感謝您的回答。我相信vector的初始容量是2,但這對我來說是新的。 – akhileshzmishra

+0

@akhileshzmishra如果你不說你需要2個元素的空間,那麼你不會得到它:)這是C++的優點之一:你不支付你不使用/想要的東西。 – Rakete1111

+0

如果添加一個移動構造函數,可以將一個字符串移動到您的類「CClass」中,那麼也可以避免使用複製構造函數。例如,通過添加: 'CClass(s​​td :: string && v):s(std :: move(v)){ cout <<「將字符串移動到構造函數中」<< endl; }' –

相關問題