STL:コンテナーから要素を削除するためのベストプラクティス

最初に話す

おそらく、STLの設計者は、APIの一貫性が非常に重要であり、短くて美しい関数名が非常に重要であり、人間の脳の能力は重要ではないと考えています...

コンテナ分類

  • 連続メモリコンテナ(vecotr、deque、queue、string)
  • リスト(はい、あなたは同じ花火です)
  • 標準の連想コンテナ(セット、マルチセット、マップ、マルチマップ)

連続メモリコンテナ

まず、2つの点を明確にします。

  1. ここで削除するということは std :: remove関数は、remove_ifに似ています。std :: list :: removeの代わりに、後者については後で説明します。
  2. さらに、消去の単一要素バージョンと間隔の削除バージョンは、削除された要素/間隔の次の要素のイテレータを返します。これは、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はここで少し過剰に設計されていると感じています...(エスケープ

おすすめ

転載: www.cnblogs.com/jo3yzhu/p/12705988.html