3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C++】vectorで特定の要素を削除(removeはeraseと組み合わせて使う)

Last updated at Posted at 2023-08-20

C++のvectorで特定の要素を削除する際に用いるremove関数は、erase関数と組み合わせて使うと安全。

remove関数だけ用いる場合

remove関数は、指定した要素を取り除くことができる。
第一引数、第二引数でイテレータで範囲を指定して、第三引数に削除したい要素を指定する。

vector<int> vec = {1, 0, 2, 0, 3, 0, 4, 0};
auto newEnd = remove(vec.begin(), vec.end(), 0);
for(auto it=vec.begin(); it != newEnd; ++it){
    cout << *it << " "; // 1 2 3 4
} 

通常、remove関数の戻り値が取り除いた後の有効領域の末尾の次を指すイテレータを返すので、それを用いて続きの処理を行う。

remove関数の注意点

しかし、関数実行後のコンテナに注目してみると、実際には取り除かれた分が前に詰められるだけで、後ろの要素は無効領域として残ったままになる。

vector<int> vec = {1, 0, 2, 0, 3, 0, 4, 0};
remove(vec.begin(), vec.end(), 0); // {1, 2, 3, 4, 3, 0, 4, 0}
/* (「3, 0, 4, 0」の部分が無効領域として残る) */

つまり、取り除いた後もコンテナサイズ自体は変わらない
コンテナサイズが変わっていないことに気づかずに、end関数や範囲for文を用いて処理を継続すると想定しないエラーを引き起こしてしまうかもしれない。

erase関数と組み合わせて使う

remove関数実行後の無効領域をerase関数で完全に削除しておくと安全。

vector<int> vec = {1, 0, 2, 0, 3, 0, 4, 0};
auto newEnd = remove(vec.begin(), vec.end(), 0);
vec.erase(newEnd, vec.end());
for(auto e: vec){ // 範囲for文も使用できる
    cout << e << " "; // 1 2 3 4
} 

こちらの方が、要素を取り除いた後の末尾のイテレータ・コンテナサイズが更新されるので、誤って無効領域にアクセスしてしまうことも未然に防ぐことができる。

3
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?