2012-07-20 13 views
17

と仮定私次のコードを持っている:移動::一back

#include <vector> 
struct A { 
    int a; 
    int x; 
}; 
int main() { 
    using namespace std; 
    A a1; 
    A a2; 
    vector<A> va; 
    va.push_back(a1); 
    va.push_back(move(a2)); 
} 

私がのstd ::ベクトルの要素がのstd ::リストとは異なり、連続して格納されていることを認識しています。上記のコードでa2は移動されましたが、vaa2のコピーは実際にはありませんか? va.push_back(a2);との違いは何ですか?

+2

'std :: move' a2は、フラットタイプ(つまり、外部データはありません)で、そのままコピーするだけなので、* nothing *とまったく同じです。 – Xeo

+0

@cdhowieありがとう。修正されました。 – ggg

+0

セマンティクスの導入については、[誰かが私にセマンティクスを説明できますか?](http://stackoverflow.com/questions/3106110/)を参照してください。 – fredoverflow

答えて

26

コンパイラが提供するコピーコンストラクタを使用しているため、実際の違いはありません。移動可能なオブジェクトを使用すると、パフォーマンスが大幅に向上し、コピーに多くの労力を要します。その場合、push_back(x)を使用するとオブジェクトのコピーが作成されますが、push_back(move(x))は、xの内容を「盗む」可能性があり、使用不能で未定義の状態になることがあるとpush_back()に通知します。

リストのベクトル(std::vector<std::list<int> >)があり、100,000個の要素を含むリストをプッシュしたい場合は、 move()を指定しないと、リスト構造全体と100,000個の要素すべてがコピーされます。 move()では、いくつかのポインタやその他の小さなデータがシャッフルされてしまいます。これははるかに高速であり、全体的なメモリ消費が少なくて済みます。

+1

なぜですか?移動は自動的に行われますが、そうではありませんか? – ForEveR

+6

@ForEveR移動できるA構造体に割り当てがないので、自動的に生成されるかどうかは関係ありません。あなたは 'int'を2つしか持たず、移動コンストラクタはコピーコンストラクタと同じことを行います:ソースオブジェクトのintに格納されている値を新しいオブジェクトに割り当てます。このタイプの移動シナリオで最適化する可能性はありません。なぜなら、このタイプはすでに得られているほど最適であるからです。 – cdhowie

+0

@cdhowie移動中に何かはいつもコピーされますか? – ggg

14

あなたがva.push_back(a2)を使用するときは、va.push_back(move(a2))を使用する場合、バージョンvector<T>::push_back(const T&)バージョンvector<T>::push_back(T&&)が...

と呼ばれます。しかし、あなたのケースでもパフォーマンスには差が

15は、存在しない、と呼ばれます非ユニオンクラスの暗黙的に定義されたコピー/移動コンストラクタ Xは、ベースとメンバーのメンバー単位のコピー/移動を実行します。

パラグラフ12.8 n3337ドラフト。

0

私は他の回答が終わっていないことに注意したい。移動コンストラクタは移動オブジェクトを設定する必要があるため、?.push_back(move(?))?.push_back(?)よりも遅くなります(実際には2つのオブジェクトをコピーしています)。

+0

移動コンストラクタは、移動したオブジェクトに対して何もする必要はありません。ヌルにリセットする必要があるポインタを移動しない限り、何もゼロにする必要はありません。 (コンパイラによって生成された移動コンストラクタは、ソースオブジェクトを覆い隠すことはありません)。 – cdhowie

関連する問題