vector<X> v;
X x;
v.push_back(x); v.push_back(x); v.push_back(x);
X
このコードがクラスのコピーコンストラクターを6回呼び出すのはなぜですか?(g ++ 4.7.2 STLを使用)
この特定のSTLの内部で何が起こっているのかを正確に知りたいのですが。
を挿入するx
とpush_back()
、メモリは最終的に再割り当てされ、新しい要素のためのスペースが確保されます。次に、すでに挿入されているメンバーを、コピーコンストラクターを使用してコピーする必要がありますX(const X&)
。
挿入した場合
v.reserve(3);
再割り当ては少なくとも最初の3秒間は防止さpush_back()
れ、その結果、への呼び出しは3回だけになります。X(const X&)
ベクトル予約を使用して、事前にベクトルにスペースを作成して、ベクトルへの要素の追加を高速化し、これが発生しないようにすることができます。
正解はstd::vector
、doubleing-array(http://en.wikipedia.org/wiki/Dynamic_array2 * N
を参照)を使用して実装され、コピーコンストラクターの約倍を呼び出すことです。
たとえばN = 100,000
、コピーコンストラクターの231,071
時間を呼び出します。指摘されているように、を呼び出すことで再割り当ての数を減らすことができますv.reserve()
。
これが起こることです:
最初のpush_backの前は、ベクトルの容量(割り当てられたスペースに収まる要素の数)は0です。したがって、最初のpush_backを実行すると、1つのアイテムにスペースが割り当てられ、コピーコンストラクターが呼び出されます(最初の呼び出し)。 。
これで容量は1つになり、別のアイテムを追加するように指示します。したがって、より多くのスペース、この場合はもう1つのアイテム用のスペースを割り当て、元のアイテムを新しいスペースにコピーする必要があります(2回目の呼び出し)。2番目のpush_backは、コピーコンストラクターを再度呼び出します(3番目の呼び出し)。
これで2の容量があり、別のアイテムを追加するように指示します。したがって、より多くのスペースを割り当て、アイテムを新しいスペースにコピーする必要があります(4回目と5回目の呼び出し)。次に、3番目のpush_backがコピーコンストラクターを再度呼び出します(6番目の呼び出し)。
他の人が指摘しているように、reserveを使用すると、スペースを事前に割り当てることができ、再割り当ての必要がなくなり、コピーコンストラクターを呼び出す必要がなくなります。