39

頭の中で明確にしたい疑問があります。std::vector最初の要素がベクトルから物理的erasestd::remove削除されてサイズが縮小され、もう 1 つの要素が要素を移動するだけで、容量は同じままになります。

これは単に効率上の理由によるものですか?を使用するとerase、a のすべての要素がstd::vector1 だけシフトされ、大量のコピーが発生します。std::remove単に「論理的な」削除を行い、物事を移動することによってベクトルを変更せずに残します。オブジェクトが重い場合、その違いが問題になる可能性がありますよね?

4

7 に答える 7

6

std::remove単純に、end()削除されていない最後の要素の 1 つ後ろを指す新しいイテレータを返します (返された値からのアイテムend()の数は、削除されるアイテムの数と一致しますが、それらの値が削除されたものと同じであるという保証はありません)削除 - それらは有効ですが未指定の状態にあります)。これは、複数のコンテナー タイプ (基本的にForwardIteratorは反復処理が可能なすべてのコンテナー タイプ) で機能するようにするためです。

std::vector::eraseend()サイズを調整した後、実際に新しい反復子を設定します。これは、のメソッドがイテレータの調整方法を実際に知っているためです ( 、などvectorでも同じことができます)。std::list::erasestd::deque::erase

removeコンテナを整理して、不要なオブジェクトを削除します。コンテナの消去機能は、コンテナが必要とする方法で「削除」を実際に処理します。それが彼らが分離されている理由です。

于 2013-10-10T13:31:12.460 に答える
5

サイズを変更するには、ベクター自体に直接アクセスする必要があることに関係していると思います。std::remove はイテレータにしかアクセスできないため、ベクトルに「ねえ、要素が少なくなりました」と伝える方法はありません。

std::remove がこのように設計されている理由については、yves Baumes の回答を参照してください。

于 2013-10-10T13:29:45.953 に答える
4

はい、それが本筋です。eraseは、パフォーマンス特性が異なる他の標準コンテナでもサポートされていることに注意してください(例: list::eraseは O(1))std::removeが、コンテナに依存せず、あらゆるタイプの前方イテレータで動作します (つまり、裸の配列でも動作します)。同じように)。

于 2013-10-10T13:27:10.640 に答える
0

すこし。remove などのアルゴリズムは、イテレータ (コレクション内の要素を表すための抽象化) で動作します。イテレータは、操作対象のコレクションのタイプを必ずしも認識していないため、コレクションのメンバーを呼び出して実際の削除を行うことはできません。

これは、アルゴリズムが任意のコンテナーに対して、またコレクション全体のサブセットである範囲に対して一般的に機能することを可能にするため、優れています。

また、あなたが言うように、パフォーマンスのために、別のアルゴリズムに渡すために論理的な終了位置にアクセスするだけでよい場合、実際に要素を削除 (および破棄) する必要はないかもしれません。

于 2013-10-10T13:39:00.790 に答える