Boucle for et list::iterator

Boucle for et list::iterator - C++ - Programmation

Marsh Posté le 18-10-2005 à 18:10:56    

Bonjour à tous,
 
j'ai un petit problème d'iterateur avec la boucle for suivante:
 

Code :
  1. for (list<float>::iterator iiplist=(iplist->begin()); iiplist!=(iplist->end()); iiplist++)
  2.     {
  3.       x=(iiplist->x)/size_cpt;
  4.       y=(iiplist->y)/size_cpt;
  5.       detA=(IG2x.pixel(x,y,0)*IG2y.pixel(x,y,0))-(IGxy.pixel(x,y,0)*IGxy.pixel(x,y,0));
  6.       trA=IG2x.pixel(x,y,0)+IG2y.pixel(x,y,0);
  7.       if (detA-(k*trA*trA)<seuil)
  8.       {
  9.         iplist->erase(iiplist);
  10.       }
  11.     }


 
En fait j'ai une erreur mémoire dès la deuxième itération, comme si l'itérateur pointait n'importe ou!
Pourtant d'après mon raisonnement, l'itérateur est initialisé en pointant vers le premier élément de la liste iplist, puis durant la 1ere itération, on rentre dans le if, donc ce 1er élément est supprimé.
L'itérateur est incrémenté par la boucle for, il passe donc sur le 2eme élément de la liste originelle, cad sur le 1er élément de la nouvelle liste... et ainsi de suite
Donc tout devrait rouler non?
Je ne vois vraiment pas d'ou vient le probleme... merci pout toute aide ^^


Message édité par lawyer666 le 19-10-2005 à 10:31:49
Reply

Marsh Posté le 18-10-2005 à 18:10:56   

Reply

Marsh Posté le 18-10-2005 à 18:23:33    

1) utilise ++i au lieu de i++
2) ensuite lis la doc "iterator erase(iterator pos)"
peut-être ne faut il pas ignorer la valeur de retour ?

Reply

Marsh Posté le 18-10-2005 à 19:21:31    

Code :
  1. #include <list>
  2. #include <iostream>
  3. #include <iterator>
  4. #include <algorithm>
  5. using namespace std;
  6. typedef list<int> List;
  7. namespace
  8. {
  9.   void List_print(const List &l)
  10.   {
  11.     copy(l.begin(), l.end(), ostream_iterator<List::value_type>(cout, ", " ));
  12.     cout << '\n';
  13.   }
  14. }
  15. int main()
  16. {
  17.   List ints;
  18.   for (int i = 0; i < 10; ++i)
  19.     ints.push_back(i);
  20.   List_print(ints);
  21.   for (List::iterator i(ints.begin()); i != ints.end(); /* nop */) {
  22.     if (*i % 2)
  23.       i = ints.erase(i);
  24.     else
  25.       ++i;
  26.   }
  27.   List_print(ints);
  28. }

Reply

Marsh Posté le 19-10-2005 à 10:31:02    

Ok, merci beaucoup ca marche nickel maintenant :)
 
Mais c'est bizarre, dans ce pdf (http://www.developpez.biz/download/stl.pdf) sur la stl, j'ai lu que la type de renvoi de erase était vide, apparemment ca doit être une petite erreur...
 
Sinon, je comprends pas trop pourquoi utiliser ++iterateur plutot que iterateur++.
Il me semble me souvenir que dans un cas l'incrément est effectué avant l'instruction, et dans l'autre cas après.
Donc ici en théorie, ca ne doit rien changer?

Reply

Marsh Posté le 19-10-2005 à 23:01:01    

pour i++ et ++i, ++i est plus performant.
 
imagine l'opérateur sur les entiers :

Code :
  1. class Int
  2. {
  3.    int m_value;
  4. public :
  5.    Int& operator++();
  6.    Int operator++(int);
  7. };
  8. Int& Int::operator++() // préfixe comme ++i
  9. {
  10.    m_value += 1;
  11.    return *this;
  12. }
  13. Int Int::operator++(int) // postfixe comme i++
  14. {
  15.    const Int n(*this);
  16.    this->operator++();
  17.    return n;
  18. }


 
tu peux voir que le postfixe est bien plus lourd car il faut incrémenter puis renvoyer une copie de l'original.
Alors autant pour les entiers de base ça n'a aucune importance puisque n'importe quel compilo sait optimiser ça, autant pour un itérateur ça correspond deux méthodes différentes dont la préfixe est la + rapide.
 
Perso (mais c'est juste mon gout) j'utilise i++ pour les entiers et les pointeurs car c'est + habituel et ++i pour les itérateurs.
 
[edit]réécriture de operator++(int) suite à remarque de Taz.


Message édité par jesus_christ le 20-10-2005 à 19:05:10
Reply

Marsh Posté le 19-10-2005 à 23:08:22    

et comme d'hab, ça réinvente l'eau chaude ... je vais les effacer les sujets utiles je pense

Reply

Marsh Posté le 19-10-2005 à 23:18:57    

bah fallait bien que tu trouves un truc pour raller, comme d'hab.
désolé mais je connais pas par coeur la liste de tous tes "sujets utiles"

Reply

Marsh Posté le 19-10-2005 à 23:52:25    

surtout que ton implémentation d'exemple est "pas terrible". On ne voit pas le lien entre ++i et i++. Bye bye le SPOT
 
edit : j'ai parlé un peu fort. Juste pour dire que ++(int) doit implémenter en utilisant ++(). ++(*this). Comme ça on voit bien le lien, et la surcharger qu'entrain ++(int).

Message cité 1 fois
Message édité par Taz le 20-10-2005 à 03:02:38
Reply

Marsh Posté le 20-10-2005 à 00:18:22    

à noter que tu n'a pas fait mieux que lui. Le type de retour de la version postfixé est incorrect, dans l'exemple de Jesus comme dans ton sujet utile.

Reply

Marsh Posté le 20-10-2005 à 02:59:14    

je vois pas là.

Reply

Marsh Posté le 20-10-2005 à 02:59:14   

Reply

Marsh Posté le 20-10-2005 à 07:26:25    

Ah ? t'as pas fait nuit blanche quand meme ?
 
Int i(3);
i++++++++;
 
que vaut i ?
 

Spoiler :

Int const operator++(int);

Reply

Marsh Posté le 20-10-2005 à 09:21:00    

Ok merci pour les explications!
 
Enfin j'ai pas tout compris à la fin de votre discussion, mais si je résume, la pré-incrémentation évite une recopie inutile?
 
Et sorry, je viens juste de découvrir les sujets utiles, je chercherai mieux la prochaine fois...

Reply

Marsh Posté le 20-10-2005 à 14:30:45    

++fab a écrit :

Ah ? t'as pas fait nuit blanche quand meme ?
[/quote]
[quotemsg=1226795,11,218706]
Int i(3);
i++++++++;
 
que vaut i ?
 

Spoiler :

Int const operator++(int);



Le truc c'est de savoir pourquoi i++ n'est pas une unnamed temporary value.

Reply

Marsh Posté le 20-10-2005 à 18:42:55    

Int i(3);
i++++; // <=> i.operator++(0).operator++(0)
//                 ^^^^^^^^^
//                   renvoie Int(3)
//                 ^^^^^^^^^^^^^^^^^^^
//                            renvoie Int(3)
//  et i vaut Int(4) !
 
 
 
la question est plutot pourquoi int i = 3;i++++ renvoie 5 ...
fichu compatibilité avec l'ancetre :/

Message cité 1 fois
Message édité par ++fab le 20-10-2005 à 18:43:43
Reply

Marsh Posté le 20-10-2005 à 19:07:09    

Taz a écrit :

surtout que ton implémentation d'exemple est "pas terrible". On ne voit pas le lien entre ++i et i++. Bye bye le SPOT
 
edit : j'ai parlé un peu fort. Juste pour dire que ++(int) doit implémenter en utilisant ++(). ++(*this). Comme ça on voit bien le lien, et la surcharger qu'entrain ++(int).


c'est vrai. je le savais mais j'avais pas tilté sur le coup. c'est en effet mieux de rappeler ++() même si ici c'est pas vraiment utile.
j'ai édité mon code en conséquence.

Reply

Marsh Posté le 20-10-2005 à 22:15:15    

++fab a écrit :

Int i(3);
i++++; // <=> i.operator++(0).operator++(0)
//                 ^^^^^^^^^
//                   renvoie Int(3)
//                 ^^^^^^^^^^^^^^^^^^^
//                            renvoie Int(3)
//  et i vaut Int(4) !
 
 
 
la question est plutot pourquoi int i = 3;i++++ renvoie 5 ...
fichu compatibilité avec l'ancetre :/


moi ça compile pas.

Reply

Marsh Posté le 21-10-2005 à 15:52:45    

i++++ ne compile pas quand tu utilises ça : Int const operator++(int) ?
ben c'est normal i++ renvoie un temporaire const auquel on applique dans la foulée une fonction non const.
C'est une manière de protéger l'utilisateur de ta classe contre sa naiveté :)
En toute rigueur, à adopter donc.

Reply

Marsh Posté le 21-10-2005 à 16:14:41    

je te parle de 'int i; i++++++;'

Reply

Marsh Posté le 21-10-2005 à 16:57:34    

diantre, je me suis vautré comme une merde la dessus  :o  
l'habitude de préplusplussage sur iterator me joue des tours :/

Reply

Marsh Posté le 21-10-2005 à 23:11:43    

moi aussi je veux un  
 
operator not_a_lvalue()

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed