Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么只在向量中已有元素时才调用move构造函数?_C++_C++11_Vector_Back_Emplace - Fatal编程技术网

C++ 为什么只在向量中已有元素时才调用move构造函数?

C++ 为什么只在向量中已有元素时才调用move构造函数?,c++,c++11,vector,back,emplace,C++,C++11,Vector,Back,Emplace,我正在尝试学习C++11的新特性。我正在XCode中测试以下代码 #include <iostream> #include <string> #include <vector> class CClass { std::string s; public: CClass() { std::cout<<"Default Constructor"<<std::endl; } CClass

我正在尝试学习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
--------------------
Constructor
--------------------

我的问题是,为什么在第二种情况下不调用move构造函数?只有在向量最初不是空的情况下才会调用它。

这是因为向量中的一个元素需要移动到新的内存位置。发生这种情况的原因是新大小将超过向量容量,因此必须为向量分配具有新容量的新内存

发件人:

如果新的
size()
大于
capacity()
,则所有迭代器和引用(包括过去的结束迭代器)都将无效。否则,只有结束迭代器的过去部分无效

迭代器和引用无效的原因相同:因为元素现在存储在内存中的一个新位置

如果在第一种情况下调用
reserve
,您将看到没有调用move构造函数:

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

谢谢你的回答。我相信向量的初始容量是2。但这对我来说是新的。@Akhileshmishra如果你不说你需要2个元素的空间,你就不会得到它:)这是C++的优点之一:你不用为你不使用/想要的东西付费。如果你添加了一个移动构造函数,可以将字符串移动到你的类
CClass
中,那么也可以避免复制构造函数。例如,添加:
CClass(std::string&&v):s(std::move(v)){         cout@snow_abstraction为什么呢?调用复制构造函数是因为传递了一个
CClass
实例,而不是一个临时的
std::string
@raket1111,这是因为
emplace\u back
如何将参数转发给
CClass
的构造函数,而不是用参数和然后复制构造的“类”。本视频的结尾提供了一些解释。
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