2017-07-03 25 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; }' –

相关问题