最初に話す
おそらく、STLの設計者は、APIの一貫性が非常に重要であり、短くて美しい関数名が非常に重要であり、人間の脳の能力は重要ではないと考えています...
コンテナ分類
- 連続メモリコンテナ(vecotr、deque、queue、string)
- リスト(はい、あなたは同じ花火です)
- 標準の連想コンテナ(セット、マルチセット、マップ、マルチマップ)
連続メモリコンテナ
まず、2つの点を明確にします。
- ここで削除するということは
std :: remove関数は、remove_ifに似ています。std :: list :: removeの代わりに、後者については後で説明します。 - さらに、消去の単一要素バージョンと間隔の削除バージョンは、削除された要素/間隔の次の要素のイテレータを返します。これは、eraseが後続の位置にあるすべての要素のイテレータを無効にするためです。
イテレーションの削除なし:remove / remove_ifはeraseと連携します
STLアルゴリズムモジュールの設計は特定のコンテナータイプから切り離されているため、さまざまなタイプのコンテナーのイテレーターを受け取って操作するだけであり、イテレーターはコンテナー内の要素反復の特定の詳細を非表示にするため、stdは次のようになります。 :removeは要素を実際に削除することはできません。コンテナの反復子しか認識せず、コンテナの消去メソッドもまったく認識しないためです。
連続メモリコンテナの場合、std :: removeおよびstd :: remove_ifの動作は、すべての適格な要素をコンテナの最後に移動し、削除する最初の要素の反復子を返します。現時点では、これらの要素は消去メソッドによって完全に削除できます。サンプルコードは次のとおりです。
vector<int> vi{1,2,2,3,4,5,6,6};
vi.erase(remove(vi.begin(), vi.end(), 2), vi.end()); // 不使用erase的返回值
vi.erase(remove_if(vi.begin(), vi.end(), [](int i){ // 不使用erase的返回值
return i > 4;
}), vi.end());
繰り返し削除:要素を削除して、他に何かしたい場合はどうしますか?
当然、消去で削除するのは簡単です。ただし、連続メモリコンテナーの場合、eraseを呼び出して単一の要素を削除し、次の要素のイテレーターを無効にします(もちろん、削除されたものも失敗します)後もループは実行され、削除された無効化されたイテレーターが再び追加され、動作は未定義です。したがって、eraseの戻り値を使用します。
vector<int> vi{1,2,2,3,4,5,6,6};
for(auto iter = vi.begin(); iter != vi.end(); /*这里啥也不干*/)
{
if(*iter == 2)
{
iter = vi.erase(iter); //这里隐含了一次++
}
else
{
++iter;
}
}
リスト
リストは、間隔削除と反復削除に連続メモリコンテナーを使用しますが、リスト:: remove()関数を直接呼び出すほうが効率的です。 、リンクされたリストの単一の要素を削除することはO(1)です。
私はいつも、STLはここで少し過剰に設計されていると感じています...(エスケープ