2017-04-02 181 views
3

我尝试将类cBar的两个实例放置到具有emplace_back函数的向量中。emplace_back调用移动构造函数和析构函数

根据reference调用emplace_back只保留向量中的位置,然后创建新的实例“in place”。现在

,我试着用它来试验:

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


class cBar 
{ 
public: 

    cBar(const int index); 
    cBar(cBar&& other); //needed for emplace_back? 
    ~cBar(); 

private: 
    cBar(const cBar& other) = delete; 
    cBar& operator=(const cBar& other) = delete; 

public: 
    int       mIndex; 

}; 




cBar::cBar(const int index) : mIndex(index) 
{ 
    std::cout << "cBar being created ..." << std::endl; 
} 
cBar::cBar(cBar&& other) : mIndex(other.mIndex) 
{ 
    std::cout << "cBar being moved ..." << std::endl; 
} 
cBar::~cBar() 
{ 
    std::cout << "cBar being destroyed ..." << std::endl; 
} 

int main() 
{ 
    std::vector<cBar> mBars; 

    std::cout << "Begin to create 2 cBar instance, I am expecting 2 \"cBar being created ...\" messages here" << std::endl; 
    mBars.emplace_back(0);//this supposed to call only cBar(const int index) constructor, and nothing more 
    mBars.emplace_back(1);//this works as expected, only one constructor call 

    //destroy all 
    std::cout << "Destroy the 2 isntances (this works, I see the two expected \"cBar being destroyed ...\" messages here" << std::endl; 
    mBars.clear(); 

    std::cin.get(); 
    return 0; 
} 

输出:

Begin to create 2 cBar instance, I am expecting 2 "cBar being created ..." messages here 
cBar being created ... 
cBar being moved ... 
cBar being destroyed ... 
cBar being created ... 
Destroy the 2 isntances (this works, I see the two expected "cBar being destroyed ..." messages here 
cBar being destroyed ... 
cBar being destroyed ... 

如果你运行上面的一个,你会看到第一emplace_back“到位”创建实例,但是会立即调用移动构造函数,然后调用析构函数。

更奇怪的是,在第二个emplace的情况下,我看到了预期的行为:只有一个构造函数调用。

我有两个问题:

  1. 为什么我需要在我的类来定义移动构造函数,如果我只是想emplace_back项目,而从不使用的push_back。

  2. 在创建第一个实例的情况下,为什么移动构造函数,然后调用析构函数?如果我访问第一个实例的数据似乎都正确,所以我不知道为什么移动构造函数和析构函数被调用。

我使用Visual Studio 2015年

输出与向量的大小在每个步骤:

Begin to create 2 cBar instance, I am expecting 2 "cBar being created ..." messages here 
Vector size:0 
cBar being created ... 
Vector size:1 
cBar being moved ... 
cBar being destroyed ... 
cBar being created ... 
Vector size:2 
Destroy the 2 isntances (this works, I see the two expected "cBar being destroyed ..." messages here 
cBar being destroyed ... 
cBar being destroyed ... 
+3

在测试前添加'mBars.reserve(9);''。 –

回答

3

2.在创建第一个实例的情况下,为什么移动构造函数,然后调用析构函数?

因为插入第二个元素emplace_back导致重新分配;需要扩展vector的内部存储,旧存储中的元素必须复制/移动到新存储,然后销毁。

1.为什么我需要在我的类中定义一个移动构造函数,如果我只想emplace_back项目,并且从不使用push_back。

如上述说明所述,vector需要通过复制/移动操作来移动元素。所以你必须定义该类的副本或移动构造函数。这对于emplace_backpush_back都是如此,因为它们都将元素添加到vector并可能导致重新分配。

+1

详细答案,谢谢! – Avithohol

1

赔率是你的向量的容量是一个,而当你把第二个元素,它必须调整矢量大小。这会变成一堆被记忆中移动的东西,以及你看到的症状。

Kerreks的建议是好的。 我建议在每次操作之前和之后打印矢量容量,以查看容量更改是否是原因。

+0

希望我能一次标出两个答案。谢谢您的帮助!用输出编辑问题。 – Avithohol