2016-11-07 6 views
2

これはデモクラスです。クラスをコピーしたくないので、コピーコンストラクタを削除します。私はこのコンストラクタ 'MyClass(型の型)'を使用するvector.emplace_backをします。しかし、これらのコードはコンパイルされません。どうして?C++のベクトルemplace_backがコピーコンストラクタを呼び出す

class MyClass 
{ 
public: 
    typedef enum 
    { 
     e1, 
     e2 
    } Type; 
private: 
    Type _type; 
    MyClass(const MyClass& other) = delete; // no copy 
public: 
    MyClass(): _type(e1) {}; 
    MyClass(Type type): _type(type) { /* the constructor I wanted. */ }; 
}; 

std::vector<MyClass> list; 
list.emplace_back(MyClass::e1); 
list.emplace_back(MyClass::e2); 
+0

問題を解決するには、デフォルトの移動コンストラクタを追加します。可動式を望まない場合は、オプションがさらに制限されます –

+0

ありがとう、私は移動コンストラクタを書くことを選択します。 – wqyfavor

答えて

5

それはそのストレージを成長させる必要がある場合、それは要素をコピーすることができるようにコピーコンストラクタがvectorによって必要とされます。あなたはvector

のための文書を読むことができます

TはCopyAssignableと コピーコンストラクトの要件を満たす必要があります。 (C++ 11まで)

に課される要件は、 コンテナで実行される実際の操作によって異なります。一般に、要素タイプは完全な タイプであり、消去可能の要件を満たしている必要がありますが、多くのメンバ関数 は厳しい要件を課しています。 (C++ 11以降)

要素に課される要件は、コンテナで実行される実際の操作( )によって異なります。一般に、 要素タイプが消去可能の要件を満たしている必要がありますが、多くのメンバ 関数は厳しい要件を課しています。 アロケータがアロケータの完全性の要件を満たしている場合、このコンテナ(ただし、 のメンバーではない)は、不完全な要素型でインスタンス化できます。

いくつかのログが出力が

create 1 
create 2 
create 3 
copy 1 
copy 2 

ですから、emplace_back要素を作成するために必要なコンストラクタを使用しないことが可能であるあなたが

For this code

class MyClass 
{ 
public: 
    typedef enum 
    { 
     e1 = 1, 
     e2 = 2, 
     e3 = 3, 
    } Type; 
private: 
    Type _type; 
public: 
    MyClass(Type type): _type(type) { std::cout << "create " << type << "\n"; }; 
    MyClass(const MyClass& other) { std::cout << "copy " << other._type << "\n"; } 
}; 

int main() { 
    std::vector<MyClass> list; 
    list.reserve(2); 
    list.emplace_back(MyClass::e1); 
    list.emplace_back(MyClass::e2); 
    list.emplace_back(MyClass::e3); 
} 

に何が起こっているのか理解するのを助けることができますストレージを拡張する必要がある場合はコピーコンストラクタを呼び出します。 reserveには、十分な容量を事前に呼び出して、コピーコンストラクターを呼び出す必要がなくなります。


あなたが本当にそれはコピー構築可能になりたくない何らかの理由で、あなたはlistとして代わりにstd::vectorstd::listを使用することができた場合はリンクリストとして実装され、それは要素を移動する必要はありません。

http://coliru.stacked-crooked.com/a/16f93cfc6b2fc73c

+0

私はC++を初めてお世話になりました。 – wqyfavor

+0

pre-C++ 11の動作の一部を太字にしました。残りの見積もりでは、C++ 11で変更された動作、特に太字部分が適用されなくなったことが説明されています。 –

+0

@ブライアン・チェン私はあなたがこれを意味すると思うhttp://coliru.stacked-crooked.com/a/2dea811906d90d84 –

0

問題のためだけの精度。コンテナの再割り当てが発生したときにオブジェクトのコピー構築を使用したくない場合は、実際には移動コンストラクタで可能ですが、noexcept指定がある場合のみ可能です。

コンテナは、コンディショナが例外をスローする可能性がある場合は、コンテナ要素を移動することを拒否します。コンテナがクリーニングできない不良状態のコンテナにつながる可能性があるからです。なぜなら、例外をスローしないと確信しているときには、moveコンストラクタをnoexceptとして指定するのが一般的には良い習慣である理由です。

関連する問題