09項 消去オプションは注意して選択しよう
消去オプションは注意して選択しよう
コンテナからある値を持つ要素を削除する場合を考えます。
連続メモリコンテナ(vector,deque,string)の場合は、eraseとremoveを組み合わせて使います。
vector<type> c; ... c.erase(remove(c.begin(), c.end(), value), c.end());
listの場合は、メンバ関数removeを使います。
list<type> c; ... c.remove(value);
標準連想コンテナの場合は、eraseを使います。
set<type> c; ... c.erase(value);
コンテナごとに効率的な削除を使い分けるようにします。
コンテナから、ある述語(boolを返す関数)がtrueを返すオブジェクトをすべて削除する場合を考えます。
連続メモリコンテナの場合は、eraseとremove_ifを組み合わせて使います。
bool badValue(type x);
vector<type> c;
...
c.erase(remove_if(c.begin(), c.end(), badValue),
c.end);
listの場合は、remove_ifを使います。
bool badValue(type x);
list<type> c;
...
remove_if(c.begin(), c.end(), badValue);
標準連想コンテナの場合は、ループを使います。
bool badValue(type x); set<int> s; ... typedef set<int>::iterator itr; for (itr i = s.begin(), end = s.end(); i != end; ){ if (badValue(*i)) s.erase(i++); else ++i; }
この時、"for(itr i = s.begin(), end = s.end(); i != end; ++i)"のようにしてはいけません。
erase(i)が実行された時にiが無効化されてしまい、インクリメントした時に問題となるからです。
for (itr i = s.begin(), end = s.end(); i != end; i++){ //インクリメント時に問題が起こる if (badValue(*i)) s.erase(i); }