リストを調べてすべての偶数を削除するリストイテレータがあります。リストイテレータを使用して数値を正しく出力することはできますが、リストのremove()を使用して、逆参照されたイテレータを渡すことはできません。
Remove()ステートメントが有効な場合、* itrが破損することに気づきましたか?誰かがこれを説明できますか?
#include <iostream>
#include <list>
#define MAX 100
using namespace std;
int main()
{
list<int> listA;
list<int>::iterator itr;
//create list of 0 to 100
for(int i=0; i<=MAX; i++)
listA.Push_back(i);
//remove even numbers
for(itr = listA.begin(); itr != listA.end(); ++itr)
{
if ( *itr % 2 == 0 )
{
cout << *itr << endl;
listA.remove(*itr); //comment this line out and it will print properly
}
}
}
上記のコードにはいくつかの問題があります。まず、remove
は、削除された要素を指しているイテレータを無効にします。次に、イテレータの使用を続行します。 remove
が複数の要素を削除する可能性があるため、一般的なケースでは(あなたの要素ではありませんが)どの要素が消去されるかを判断するのは困難です。
次に、おそらく間違った方法を使用しています。 Removeは、リスト内のすべてのアイテムを繰り返し処理して、一致する要素を探します。これは、1つしかないため、非効率的です。 erase
メソッドを使用する必要があるようです。おそらく、イテレータの位置にあるアイテムのみを消去する必要があります。 erase
の良いところは、次の有効な位置にあるイテレータを返すことです。それを使用する慣用的な方法は次のようなものです:
//remove even numbers
for(itr = listA.begin(); itr != listA.end();)
{
if ( *itr % 2 == 0 )
{
cout << *itr << endl;
itr=listA.erase(itr);
}
else
++itr;
}
最後に、remove_if
を使用して同じことを行うこともできます。
bool even(int i) { return i % 2 == 0; }
listA.remove_if(even);
参照している要素を削除した後は、イテレータを使用できません。
ただし、remove()
の後に削除されていないアイテムを参照するリストイテレータは有効なままである必要があります。
次のようなものを使用できますか?
container.erase(it++);
私はこの例を試しました:
int main(){
list<int>*a=new list<int>;
a->Push_back(1);
a->Push_back(2);
a->Push_back(3);
list<int>::iterator I;
I=a->begin(); ++I;
a->erase(I++);
cout<<*I<<endl;
}
思い通りに3が表示されました。これが有効なのか、「機能する場合と機能しない場合がある」のかはわかりません。
編集:多分それはコンパイラのせいです。たとえば、私が使用しているコンパイラ(GNU gcc-g ++)は、リスト(std::)を循環として扱います。つまり、list-> end()の後にイテレータを増やすと、先頭に移動します。