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);
}