2017-04-02 130 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

相關問題