ホームページ  >  記事  >  バックエンド開発  >  反復中に std::vector から要素を安全に削除するにはどうすればよいですか?

反復中に std::vector から要素を安全に削除するにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-10-30 07:35:02336ブラウズ

How to Safely Remove Elements from a std::vector During Iteration?

反復中に std::Vector から要素を削除する

要素のベクトルがあり、反復中に項目を削除する必要がある場合、erase() メソッドは問題を引き起こす可能性があります。要素を消去すると、後続の要素を指すすべての反復子が無効になります。

反復子と Erase()

次のコードを考えてみましょう。

<code class="cpp">std::vector<std::string> m_vPaths;
...
for (auto iter = m_vPaths.begin(); iter != m_vPaths.end(); iter++) {
  std::string strPath = *iter;
  if (::DeleteFile(strPath.c_str())) {
    m_vPaths.erase(iter);
    // Iterators become invalid after erase
  }
}</code>

最初にファイルの削除が成功すると、次の要素を指す反復子は無効になります。これにより、反復の継続が複雑になります。

2 つのベクトルの使用

解決策の 1 つは、2 つのベクトルを使用することです。1 つは反復処理用、もう 1 つは削除される要素の保存用です。 。これは機能しますが、追加のメモリ オーバーヘッドと複雑さが生じます。

代替データ構造

次のような、反復中に要素を削除するのに適したデータ構造があります。

  • std::set> (順序付けされ、一意であり、自然に降順でソートされます)
  • std::unowned_set (順序付けされておらず一意です)

これらの構造体は、値の並べ替えられたコレクションまたは順序付けされていないコレクションを維持し、削除しても他の要素は無効になりません。

std::remove_if の使用

または、std::remove_if() アルゴリズムを使用して、特定の要素を削除する前にベクターから削除することもできます。これにより、イテレータが有効なままであることが保証されます。

<code class="cpp">auto iter_new_end = std::remove_if(m_vPaths.begin(), m_vPaths.end(),
  [](const std::string& strPath) {
    return ::DeleteFile(strPath.c_str());
  });
m_vPaths.erase(iter_new_end, m_vPaths.end());</code>

結論

特定の要件に応じて、次から最適なアプローチを選択できます。

  • 反復子の使用には注意が必要
  • 2 つのベクトルの維持
  • 代替データ構造の利用
  • std::remove_if() の採用

以上が反復中に std::vector から要素を安全に削除するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。