2017-04-02 1 views
3

私は、クラスcBarの2つのインスタンスをemplace_back関数を持つベクトルに置き換えようとします。emplace_backはコンストラクタを移動し、デストラクタを呼び出す

referenceによると、emplace_backを呼び出すと、ベクター内の場所が予約され、「インプレース」という新しいインスタンスが作成されます。

今、私はそれを試してみました:

#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は「場所に」インスタンスを作成していることがわかりますその後すぐに移動コンストラクタを呼び出し、デストラクタが呼び出されます。

2番目のemplaceの場合は、予想される動作が表示されます。コンストラクタが1つだけ呼び出されます。

は、私は2つの質問がある:私はちょうど項目をemplace_back、そして一backを使用しないようにしたい場合、私は私のクラスに移動コンストラクタを定義する必要がありますなぜ

  1. 最初のインスタンス作成の場合、なぜ移動コンストラクタ、次にデストラクタが呼び出されますか?私が最初のインスタンスのデータにアクセスすると、すべて正しいと思われるので、なぜ移動コンストラクタとデストラクタが呼び出されたのかわかりません。

私は、各ステップにおけるベクトル・サイズでの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で2番目の要素を挿入すると、再割り当てが行われるため、 vectorの内部ストレージを拡張する必要があり、古いストレージの要素を新しいストレージにコピー/移動してから破棄する必要があります。

1.私はちょうどemplace_backアイテムにしたい、そしてpush_backを使用しない場合、私は自分のクラスで移動コンストラクタを定義する必要があります。

上記のように、vectorは、コピー/移動操作で要素を移動する必要があります。したがって、クラスのコピーまたは移動コンストラクタを定義する必要があります。emplace_backpush_backの両方に適用されます。これは両方とも要素をvectorに追加し、再割り当てが行われる可能性があるためです。

+1

詳細な回答、ありがとう! – Avithohol

1

オッズは、あなたのベクトルの容量は一つであった、とあなたは2番目の要素を入れたときにされていますベクトルのサイズを変更する必要がありました。それは記憶の中に動かされるものの束と、あなたが見る症状に変わることがあります。

Kerreksのアドバイスは良いです。 容量の変更が原因であるかどうかを確認するために、各操作の前と後にベクトル容量を印刷することをお勧めします。

+0

私はすぐに2つの答えにフラグを付けることができました。助けてくれてありがとう!出力に質問を編集しました。 – Avithohol

関連する問題