【C++学習|初心者向け】C++20でスマートに要素を削除!std::eraseとstd::erase_ifの活用術

1. 導入:なぜstd::eraseが重要なのか

C++でプログラミングをしていると、動的配列であるstd::vectorなどから「特定の条件に一致する要素をすべて削除したい」という場面によく遭遇します。これまでのC++(C++17以前)では、イテレータを操作する「erase-removeイディオム」という少し複雑な書き方をする必要がありました。しかし、C++20から導入されたstd::eraseおよびstd::erase_ifを使えば、誰でも直感的かつ安全に、短いコードで要素を削除できるようになりました。コードの可読性を高め、バグを減らすために必須の知識です。

2. 基礎知識:コンテナからの削除の仕組み

コンテナ(std::vectorやstd::listなど)から要素を削除する際、単にループで削除しようとすると、削除によってイテレータが無効化され、プログラムがクラッシュする原因になります。これまで使われてきたerase-removeイディオムは、削除したい要素をコンテナの末尾に寄せ集めてから一気に消去するという手法でしたが、初心者には少し難解でした。std::eraseとstd::erase_ifは、これらの複雑な処理を内部で隠蔽してくれる便利な「非メンバ関数」です。

3. 実装/解決策

使い方は非常にシンプルです。
std::eraseは、特定の値と一致する要素をすべて削除します。
std::erase_ifは、ラムダ式(条件式)を渡して、その条件に当てはまる要素をすべて削除します。

どちらも、コンテナを直接書き換えるため、戻り値として「実際に削除された要素の数」が返ってきます。

4. サンプルプログラム

以下のコードをコピーして、C++20環境で実行してみてください。

include
include
include

int main() {
// 数値のリストを作成
std::vector numbers = {1, 10, 2, 10, 3, 4, 10};

// 1. std::erase: 値が10のものをすべて削除
std::erase(numbers, 10);

// 2. std::erase_if: 偶数をすべて削除(ラムダ式を使用)
std::erase_if(numbers, [](int n) {
return n % 2 == 0;
});

// 結果の確認
std::cout << "残った要素: "; for (int n : numbers) { std::cout << n << " "; } // 出力結果は 1, 3 となります return 0; }

5. 応用・注意点

現場で使う際のポイントが2つあります。
まず、パフォーマンスについてです。std::vectorのようなメモリが連続しているコンテナに対しては、これらを使うと効率的ですが、削除するたびに後ろの要素が前に詰められるため、削除対象が大量にある場合は計算量に注意してください。
次に、イテレータの無効化です。std::erase系関数を使用している最中に、別のスレッドから同じコンテナを操作するのは危険です。また、これらを使うことで「イテレータをループで回しながら削除する」というアンチパターンを避けることができるため、積極的に最新の関数へ書き換えていくことをおすすめします。

コメント

タイトルとURLをコピーしました