web-dev-qa-db-ja.com

ベクトルをクリアまたは消去するC ++の最速の方法

0〜5000の要素でベクトルを定期的に埋めるコードがあります。最大値が5000を超えることはありません。ベクトルを複数回初期化する代わりに、一度だけ実行したいです。

vector<struct> myvector;
myvector.reserve(5000);

ただし、ベクトルを再度塗りつぶすには、容量を変更せずに最初にベクトルをクリアする必要があります。したがって、通常はmyvector.clear()を呼び出します。

これはO(n)操作です。これのパフォーマンスを向上させるためにできる簡単なことはありますか?

34
user788171

構造体に非自明なデストラクタがある場合、空になる方法に関係なく、ベクトルのすべての要素に対してそれを呼び出す必要があります。構造体に取るに足らないデストラクタしかない場合、コンパイラまたは標準ライブラリの実装は、破壊プロセスを最適化してO(1)操作を与えることができます。

39
Vaughn Cato

clear()のコストは、格納されたオブジェクトが何であるか、特に、それらに些細なデストラクタがあるかどうかに大きく依存します。型に単純なデストラクタがない場合、呼び出しは保存されているすべてのオブジェクトを破棄する必要があり、実際にはO(n)操作ですが、これ以上良いことはできません。

さて、保存された要素に取るに足らないデストラクタがある場合、実装はコストを最適化でき、clear()は安価なO(1)操作(サイズをリセットするだけです- endポインター)。

漸近的な複雑さを理解するには、それが何について話しているのかを知る必要があることを忘れないでください。 clear()の場合、呼び出されるデストラクタの数を表しますが、コスト(非表示)が0の場合、操作は何もしません。

既存のアイテムをベクターから削除するために行うことはすべて、破壊される各アイテムのデストラクタを(潜在的に)呼び出す必要があります。したがって、コンテナの観点からは、線形の複雑さを期待できます。

それは、ベクターにどのような種類のアイテムを保存するかという問題だけです。コンパイラが事前にデストラクタを呼び出さないことを知っている/知っているintのようなものを保存する場合、削除が一定の複雑さで終わる可能性は少なくともかなりあります。

ただし、構文を変更すると(たとえば、clear() vs. resize() vs. erase(begin(), end()))大幅な違いが生じるとは思いません。 Nデストラクターを呼び出す(スレッドがない場合)構文は、O(N)操作です。

10
Jerry Coffin