std :: listから要素を削除することはできますか?例:so:std :: listからiteratingしている要素を削除することはできますか?
std::list<int> lst;
//....
for (std::list<int> itr = lst.begin(); itr != lst.end(); itr++)
{
if (*itr > 10)
lst.remove(*itr);
}
? なぜですか?
std :: listから要素を削除することはできますか?例:so:std :: listからiteratingしている要素を削除することはできますか?
std::list<int> lst;
//....
for (std::list<int> itr = lst.begin(); itr != lst.end(); itr++)
{
if (*itr > 10)
lst.remove(*itr);
}
? なぜですか?
正しいコードは以下の通りです:あなたがリストから項目を削除すると(それが削除されている項目を指している場合。)
for (std::list<int>::iterator itr = lst.begin(); itr != lst.end(); /*nothing*/)
{
if (*itr > 10)
itr = lst.erase(itr);
else
++itr;
}
、あなたはイテレータを無効にする可能性があるので、あなたはerase
を使用して削除する必要があります(次の項目を指す有効なイテレータを返します)。
さらに良いアイデアがstd::remove_if
を使用することになります。
bool greater_than_10(int x)
{
return x > 10;
}
lst.remove_if(greater_than_10);
コンパイラがlambdasをサポートしている場合、あなたも短いそれを置くことができます。
lst.remove_if([](int x){ return x > 10; });
(私は私のように、このコードをテストしていませんコンパイラはそれほど新しいものではなく、ラムダ関数は感謝して@ John Diblingの答えから盗まれています)。
実際には、リストから消去するとonly the iterators pointing to the item being deletedが無効になります。ただし、他のSTLコンテナにはこのプロパティはありません。
他のSTLコンテナ(たとえばベクトル)では、制約がより厳密になることに注意してください。コンテナから削除すると、削除されたアイテムを指すイテレータだけでなく、他のイテレータも無効になります。したがって、それらの反復処理中にそのコンテナから削除することは、さらに問題になります。
私はできると思いますが、remove
の代わりにerase
メソッドで行うことができる要素の削除後にイテレータを再割り当てする必要があります。
それ以外の場合は安全でないため、実行しないでください。
いいえ。例コードでは、itr
が無効になり、未定義の動作が発生します。しかし、これはうまくいく:
イテレータのプリインクリメントは良い考えです。これに合わせてコードを変更しました。今度は、例のコードはまったく同じです:) – Vlad
いいえ、できません。
しかし、あなた(とすべきである)「10 'よりも大きいと言うファンクターと一緒にstd::remove_if
を使用することができ、このように:
#include <list>
#include <algorithm>
int main()
{
std::list<int> lst;
lst.push_back(1);
lst.push_back(12);
lst.push_back(1);
//....
lst.erase(std::remove_if(lst.begin(), lst.end(), std::bind2nd(std::greater<int>(), 10)), lst.end());
}
もう一つ、これを行うために、より汎用的な方法は、独自のカスタムファンクタを書くことです。ここには、is_a_match
ファンクタtrue
を返します。チェックされている値が10より大きい場合。あなたがC++ 0xの準拠コンパイラの利点を持っている場合は
#include <list>
#include <algorithm>
#include <functional>
struct is_a_match : public std::unary_function<int, bool>
{
is_a_match(int val) : val_(val) {};
bool operator()(int victim) const { return victim > val_; }
private:
int val_;
};
int main()
{
std::list<int> lst;
lst.push_back(1);
lst.push_back(12);
lst.push_back(1);
//....
lst.erase(std::remove_if(lst.begin(), lst.end(), is_a_match(10)));
}
は、あなたもラムダを使用することができ、作る:あなたは、それが「一致」に、あなたのケースであらゆる手段に対応するようにtrue
を返すようにoperator()
を再定義することができますそれは、可能なファンクタを取り除くためにとイテレータの説明についてはhttp://www.cppreference.com/wiki/iterator/startを参照してください。多くの場合
#include <list>
#include <algorithm>
int main()
{
std::list<int> lst;
lst.push_back(1);
lst.push_back(12);
lst.push_back(1);
//....
lst.erase(std::remove_if(lst.begin(), lst.end(), [](int v) {return v > 10;}));
}
実際には、 'list'自身の' remove_if'メンバ関数を持っています: 'lst.remove_if(std :: bind2nd(std :: greater
@ Fred:Trueですが、これはより一般的で、 'list'以外のコレクションでこれを行う方法を教えています。私はScott Meyersとは対照的に、非メンバ関数を好んでおり、一般的な考え方も拡張しています。 –
@ジョン:同意。リストのほうが最適なので、 'list'はこのようなメンバ関数(および' sort'など)を提供すると思います。それはあまりにも消去/イディオムを削除するよりも見た目に見えます。しかし、私はあなたの点を感謝します。 –
により表現コードを記述します。
ノートのカップル:あなたの代わりにポストインクリメント演算子の前インクリメント演算子(++itr
)を使用する必要があります
itr++
)
[STLリストの項目を消去する](http://stackoverflow.com/questions/501962/erasing-items-from-an-stl-list) – sth
はい、しかしそうではありません。 –
可能な複製[要素を反復処理しながらstd :: listから削除することはできますか?](http://stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while- iterating-through-it) – AShelly