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

akh*_*hra 3 c++ vector back c++11 emplace

我正在尝试学习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;
}
Run Code Online (Sandbox Code Playgroud)

当我取消注释后退时,我得到以下结果:

Constructor
Copy Constructor
--------------------
Constructor
Move Constructor
--------------------
Run Code Online (Sandbox Code Playgroud)

否则,如果我发表评论,我会得到:

Constructor
--------------------
Constructor
--------------------
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么在第二种情况下不调用移动构造函数?它仅在第一种情况下被调用,当vector最初不为空时.

Rak*_*111 7

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

来自std::vector::emplace_back:

如果new 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
Run Code Online (Sandbox Code Playgroud)