2009-06-19 6 views
14

リストを経由してすべての偶数を削除するリストイテレータがあります。私はリストのイテレータを使用して数字をうまく印刷できますが、リストのremove()を使用したり、逆参照されたイテレータを渡すことはできません。List Iterator 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 
     } 
    } 
} 

答えて

41

上記のコードにはいくつか問題があります。まず、removeは、削除された要素を指すイテレータを無効にします。その後、イテレータを使用し続けます。 2つ以上の要素を削除できるので、どの要素(通常はあなたのものではない)が消去されるかはわかりにくいです。

第2に、間違った方法を使用している可能性があります。削除すると、一致する要素を探すリスト内のすべての項目を繰り返し処理します.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); 
2

参照された要素を削除した後は、イテレータを使用することはできません。

ただし、remove()の有効性を維持した後、削除されていないアイテムを参照するイテレータをリストします。

-1

イテレータは構造体の長さに依存するため、ほとんどのイテレータでは、イテレータが使用されている間はリストを変更できません。リストを変更して変更したい場合は、イテレータとは独立したループを使用する必要があります。

+4

STLイテレータは構造体の長さに依存しないことを指摘しておきます。反復子は、特定の要素を削除することを可能にすることがよくあります。例えば、反復子を越えて項目を削除することができるベクトル反復子、反復子によって指されていないものを削除するリスト反復子 –

0

は、我々はこのようなものを使用することができますそれを使用するための慣用的な方法は、このようなものである

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つ表示されました。今、私はこれが有効か、「時には時にはうまくいかない」ものかどうかはわかりません。

EDIT:コンパイラの可能性があります。例えば、コンパイラは(GNU gcc-g ++)を使ってリスト(std::)を循環的に扱っています。つまり、list-> end()の後にイテレータを増やすと最初に置かれます。

+0

これは 'std :: list'イテレータそれらのイテレーターは、それらが指している要素が削除されたときにのみ無効になります。しかし、これは、 'std :: vector'イテレータでは機能しません。なぜなら、それらのイテレータは、それらが指している要素またはそれらが指す前の要素が削除されたときに無効になるからです。 – David