 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Michaël Delva Guest
|
Posted: Mon Feb 23, 2004 11:00 am Post subject: Vector et erase |
|
|
Bonjour à tous,
quand je parcours un vecteur à l'aide d'une boucle for, et qu'un élément
de ce vecteur doit être supprimé, est-ce que faire un erase() de
l'itérateur correspondant va affecter la suite de ma boucle? Ex:
for (std::vector<int>::const_iterator ite = vect.begin(); ite !=
vect.end(); ++ite)
if (*ite ==
vect.erase(*ite);
Après le erase(*ite), est-ce que c'est bien l'élément "après" qui va être
analysé?
J'espère m'être bien fait comprendre...
Merci d'avance
|
|
| Back to top |
|
 |
Nicolas Guest
|
Posted: Mon Feb 23, 2004 11:14 am Post subject: Re: Vector et erase |
|
|
ca dépend de l'implementation et du type d'objet pointé par l'iterateur.
il faut voir si dans l'implementation du vector<> (dans le man) le fait
d'effacer un element invalide l'iterateur.
en général, oui.
en gros:
v.erase(*iter);
*iter = 10; ca plante !
pour eviter ce genre de question, il faut préparer une iteration +1 :
ci = v.begin();
cn = ci++;
if (*ci == val)
v.erase(*ci);
ci = cn;
else
ci = cn;
cn++;
....
et la c'est clair ? ;-)
|
|
| Back to top |
|
 |
Franck Branjonneau Guest
|
Posted: Mon Feb 23, 2004 11:36 am Post subject: Re: Vector et erase |
|
|
"Michaël Delva" <zoubidaman (AT) hotmail (DOT) com> écrivait:
Bonjour,
| Quote: | quand je parcours un vecteur à l'aide d'une boucle for, et qu'un
élément de ce vecteur doit être supprimé, est-ce que faire un
erase() de l'itérateur correspondant va affecter la suite de ma
boucle?
|
Sans aucun doute. vector<>::erase(it) détruis l'élément désigné par it
et retourne un itérateur sur l'élément qui suivait it avant sa
destruction.
| Quote: | J'espère m'être bien fait comprendre...
|
Très bien.
--
Franck Branjonneau <fasbjx (AT) free (DOT) fr>
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Mon Feb 23, 2004 11:57 am Post subject: Re: Vector et erase |
|
|
On Mon, 23 Feb 2004 12:14:07 +0100, Nicolas <nicolas.belan (AT) tele2 (DOT) fr>
wrote:
| Quote: | il faut voir si dans l'implementation du vector<> (dans le man) le fait
d'effacer un element invalide l'iterateur.
|
Je confirme que c'est oui : une modification du nombre d'éléments d'un
std::vector<> invalide[*] tous les itérateurs sur des éléments de ce
vector<>. Ta solution ne fonctionne donc pas non plus.
[*] Plus précisément, on n'est pas sûr qu'ils sont invalidés, mais
comme la possibilité existe, on ne peut pas prendre le risque.
--
;-)
|
|
| Back to top |
|
 |
Guillaume Brocker Guest
|
Posted: Mon Feb 23, 2004 12:39 pm Post subject: Re: Vector et erase |
|
|
Franck Branjonneau wrote:
| Quote: | Sans aucun doute. vector<>::erase(it) détruis l'élément désigné par it
et retourne un itérateur sur l'élément qui suivait it avant sa
destruction.
|
Pour revenir à l'exemple de départ, on peut le transfomer comme suit:
std::vector<int>::iterator ite = vect.begin();
for(;
{
if( ite != vect.end() )
{
if( *ite != 8 )
{
ite = vect.erase( ite );
}
else
{
ite++;
}
}
else
{
break;
}
}
--
Guillaume Brocker
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Mon Feb 23, 2004 12:53 pm Post subject: Re: Vector et erase |
|
|
Guillaume Brocker <guillaume.brocker (AT) ircad (DOT) u-strasbg.fr> writes:
| Quote: | Franck Branjonneau wrote:
Sans aucun doute. vector<>::erase(it) détruis l'élément désigné par it
et retourne un itérateur sur l'élément qui suivait it avant sa
destruction.
Pour revenir à l'exemple de départ, on peut le transfomer comme suit:
std::vector<int>::iterator ite = vect.begin();
for(;
{
if( ite != vect.end() )
{
if( *ite != 8 )
{
ite = vect.erase( ite );
}
else
{
ite++;
}
}
else
{
break;
}
}
|
Et pourquoi ne pas utiliser un while plutot que la structure etrange
for(; {
if (cond) {
...
} else {
break;
}
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
|
|
| Back to top |
|
 |
Manuel Guest
|
Posted: Mon Feb 23, 2004 12:56 pm Post subject: Re: Vector et erase |
|
|
"Michaël Delva" <zoubidaman (AT) hotmail (DOT) com> a écrit dans le message de
news:Xns94987A185378Ezoubidamanhotmailcom (AT) 212 (DOT) 27.42.69...
| Quote: | Bonjour à tous,
quand je parcours un vecteur à l'aide d'une boucle for, et qu'un élément
de ce vecteur doit être supprimé, est-ce que faire un erase() de
l'itérateur correspondant va affecter la suite de ma boucle? Ex:
for (std::vector<int>::const_iterator ite = vect.begin(); ite !=
vect.end(); ++ite)
if (*ite ==
vect.erase(*ite);
Après le erase(*ite), est-ce que c'est bien l'élément "après" qui va être
analysé?
J'espère m'être bien fait comprendre...
Merci d'avance
|
Ca ne marchera pas comme ça.
L'itérateur n'est plus valide après vect.erase().
AMHA, ce serait mieux d'écrire :
std::vector<int>::const_iterator ite = vect.begin();
while (ite != vect.end())
if (*ite ==
vect.erase(*ite++);
Mais je n'en suis pas certain.
Une meilleure solution serait d'utiliser std::remove_if :
inline bool egale_huit(int n) { return (8 == n); }
// ou avec un template, un objet fonction, ... c'est selon le besoin.
vect.erase(std::remove_if(vect.begin(), vect.end(), egale_huit),
vect.end());
En espérant que ça aidera. :-)
--
- Manuel
to reply, swap the name with the domain.
|
|
| Back to top |
|
 |
Franck Branjonneau Guest
|
Posted: Mon Feb 23, 2004 1:08 pm Post subject: Re: Vector et erase |
|
|
Jean-Marc Bourguet <jm (AT) bourguet (DOT) org> écrivait:
| Quote: | Guillaume Brocker <guillaume.brocker (AT) ircad (DOT) u-strasbg.fr> writes:
Franck Branjonneau wrote:
Sans aucun doute. vector<>::erase(it) détruis l'élément désigné
par it et retourne un itérateur sur l'élément qui suivait it
avant sa destruction.
Pour revenir à l'exemple de départ, on peut le transfomer comme
suit:
[ une horrible boucle for ]
Et pourquoi ne pas utiliser un while plutot que la structure etrange
for(; {
if (cond) {
...
} else {
break;
}
|
Ou alors :
vect.erase(std::remove_if(vect.begin(), vect.end(),
std::bind2nd(std::equal_to< int >(), 5)), vect.end());
--
Franck Branjonneau <fasbjx (AT) free (DOT) fr>
|
|
| Back to top |
|
 |
Alain Migeon Guest
|
Posted: Mon Feb 23, 2004 2:50 pm Post subject: Re: Vector et erase |
|
|
In article <Xns94987A185378Ezoubidamanhotmailcom (AT) 212 (DOT) 27.42.69>,
[email]zoubidaman (AT) hotmail (DOT) com[/email] says...
| Quote: | Bonjour à tous,
quand je parcours un vecteur à l'aide d'une boucle for, et qu'un élément
de ce vecteur doit être supprimé, est-ce que faire un erase() de
l'itérateur correspondant va affecter la suite de ma boucle? Ex:
for (std::vector<int>::const_iterator ite = vect.begin(); ite !=
vect.end(); ++ite)
if (*ite ==
vect.erase(*ite);
Après le erase(*ite), est-ce que c'est bien l'élément "après" quiva être
analysé?
J'espère m'être bien fait comprendre...
Merci d'avance
|
Une solution sûre consiste à mettre les itérateurs des éléments que tu
veux supprimer dans un autre vecteur. Et ensuite de parcourir ce
vecteur.
Alain
Exemple :
#include <vector>
using std::vector;
typedef std::vector <int> VInt;
typedef std::vector <VInt::iterator> VItInt;
int main ()
{
VInt vInt;
VInt::iterator itInt;
VItInt vItInt;
VItInt::iterator itItInt;
// ...
// remplissage de vInt.
// ...
for (itInt = vInt.begin (); itInt != vInt.end (); ++ itInt)
{
if (*itInt ==
vItInt.push_back (itInt);
}
for (itItInt = vItInt.begin (); itItInt != vItInt.end (); ++ itItInt)
vInt.erase (*itItInt);
vItInt.clear ();
}
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Mon Feb 23, 2004 2:56 pm Post subject: Re: Vector et erase |
|
|
Alain Migeon <agm (AT) dk (DOT) rovsing> writes:
| Quote: | In article <Xns94987A185378Ezoubidamanhotmailcom (AT) 212 (DOT) 27.42.69>,
[email]zoubidaman (AT) hotmail (DOT) com[/email] says...
Bonjour à tous,
quand je parcours un vecteur à l'aide d'une boucle for, et qu'un élément
de ce vecteur doit être supprimé, est-ce que faire un erase() de
l'itérateur correspondant va affecter la suite de ma boucle? Ex:
for (std::vector<int>::const_iterator ite = vect.begin(); ite !=
vect.end(); ++ite)
if (*ite ==
vect.erase(*ite);
Après le erase(*ite), est-ce que c'est bien l'élément "après" qui va être
analysé?
J'espère m'être bien fait comprendre...
Merci d'avance
Une solution sûre consiste à mettre les itérateurs des éléments que tu
veux supprimer dans un autre vecteur. Et ensuite de parcourir ce
vecteur.
|
| Quote: | Alain
Exemple :
#include <vector
using std::vector;
typedef std::vector
typedef std::vector <VInt::iterator> VItInt;
int main ()
{
VInt vInt;
VInt::iterator itInt;
VItInt vItInt;
VItInt::iterator itItInt;
// ...
// remplissage de vInt.
// ...
for (itInt = vInt.begin (); itInt != vInt.end (); ++ itInt)
{
if (*itInt ==
vItInt.push_back (itInt);
}
for (itItInt = vItInt.begin (); itItInt != vItInt.end (); ++ itItInt)
vInt.erase (*itItInt);
vItInt.clear ();
}
|
Pas sur du tout tel qu'ecrit: les iterateurs d'un vecteur (pointant
apres l'iterateur) sont invalides apres tout effacement. Si t'iteres
a l'envers par contre, c'est correct.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
|
|
| Back to top |
|
 |
Alain Migeon Guest
|
Posted: Mon Feb 23, 2004 3:05 pm Post subject: Re: Vector et erase |
|
|
In article <pxbsmh14zew.fsf (AT) news (DOT) bourguet.org>, [email]jm (AT) bourguet (DOT) org[/email] says...
| Quote: | Alain Migeon <agm (AT) dk (DOT) rovsing> writes:
In article <Xns94987A185378Ezoubidamanhotmailcom (AT) 212 (DOT) 27.42.69>,
[email]zoubidaman (AT) hotmail (DOT) com[/email] says...
Bonjour à tous,
quand je parcours un vecteur à l'aide d'une boucle for, et qu'un élément
de ce vecteur doit être supprimé, est-ce que faire un erase() de
l'itérateur correspondant va affecter la suite de ma boucle? Ex:
for (std::vector<int>::const_iterator ite = vect.begin(); ite !=
vect.end(); ++ite)
if (*ite ==
vect.erase(*ite);
Après le erase(*ite), est-ce que c'est bien l'élément "après"qui va être
analysé?
J'espère m'être bien fait comprendre...
Merci d'avance
Une solution sûre consiste à mettre les itérateurs des éléments que tu
veux supprimer dans un autre vecteur. Et ensuite de parcourir ce
vecteur.
Alain
Exemple :
#include <vector
using std::vector;
typedef std::vector
typedef std::vector <VInt::iterator> VItInt;
int main ()
{
VInt vInt;
VInt::iterator itInt;
VItInt vItInt;
VItInt::iterator itItInt;
// ...
// remplissage de vInt.
// ...
for (itInt = vInt.begin (); itInt != vInt.end (); ++ itInt)
{
if (*itInt ==
vItInt.push_back (itInt);
}
for (itItInt = vItInt.begin (); itItInt != vItInt.end (); ++ itItInt)
vInt.erase (*itItInt);
vItInt.clear ();
}
Pas sur du tout tel qu'ecrit: les iterateurs d'un vecteur (pointant
apres l'iterateur) sont invalides apres tout effacement. Si t'iteres
a l'envers par contre, c'est correct.
|
Mea culpa.
J'ai écrit trop vite.
C'est la méthode que j'utilise pour supprimer les éléments d'un map.
Dans ce cas un itérateur reste valide jusqu'à sa suppression.
Alain
|
|
| Back to top |
|
 |
Nicolas Guest
|
Posted: Mon Feb 23, 2004 3:36 pm Post subject: Re: Vector et erase |
|
|
| Quote: |
il faut voir si dans l'implementation du vector<> (dans le man) le fait
d'effacer un element invalide l'iterateur.
Je confirme que c'est oui : une modification du nombre d'éléments d'un
std::vector<> invalide[*] tous les itérateurs sur des éléments de ce
vector<>. Ta solution ne fonctionne donc pas non plus.
|
pas forcément ... mais un peu qd meme ...
dans un cas ca marche, mais je n'ai pas tout dit (mea culpa)
si on part de la fin, et qu'on inverse la boucle (avec un reverse_iterator,
ou for(ci = end(); ci != begin(); ci--)
ca marche (avec les vector des stl sgi ...)
donc, pour etre tres précis, un erase invalide tous les iterateurs qui
pointent sur des elements qui sont après l'iterateur en erase() (simple non
?)
c'est censé retourner un iterateur. Mais d'experience, j'ai vu des STL qui
ne retournent pas l'iterateur ...
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Mon Feb 23, 2004 3:38 pm Post subject: Re: Vector et erase |
|
|
On Mon, 23 Feb 2004 15:50:37 +0100, Alain Migeon <agm (AT) dk (DOT) rovsing>
wrote:
| Quote: | Content-Transfer-Encoding: quoted-printable
|
Peux-tu éviter le quoted-printable sur Usenet ? C'est en effet assez
illisible (du style, "Une solution s=FBre consiste =E0 mettre les
it=E9rateurs des =E9l=E9ments")
Merci d'avance...
--
;-)
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Feb 23, 2004 5:20 pm Post subject: Re: Vector et erase |
|
|
Nicolas <nicolas.belan (AT) tele2 (DOT) fr> wrote
| Quote: | ca dépend de l'implementation et du type d'objet pointé par
l'iterateur.
|
Pas du tout.
| Quote: | il faut voir si dans l'implementation du vector<> (dans le man) le
fait d'effacer un element invalide l'iterateur.
|
En général, le fait de supprimer un élément d'une collection invalide
tout itérateur qui désigne l'élément supprimé. Étant donné la façon
comment fonctionne la STL, c'est difficile à voir comment ça pourrait
être autrement.
Dans le cas de std::vector, le fait de supprimer un élément invalide non
seulement les itérateurs qui désigne l'élément, mais tous les itérateurs
qui le suivent.
| Quote: | en général, oui.
en gros:
v.erase(*iter);
*iter = 10; ca plante !
pour eviter ce genre de question, il faut préparer une iteration +1 :
ci = v.begin();
cn = ci++;
if (*ci == val)
v.erase(*ci);
ci = cn;
else
ci = cn;
cn++;
...
et la c'est clair ?
|
Selon la norme, ça ne marche pas non plus.
En fait, vector<>::erase renvoie un itérateur à l'élément qui suit le
dernier élément supprimé. On pourrait donc écrire :
std::vector<T>::iterator current = v.begin() ;
while ( current != v.end() ) {
if ( *current == val ) {
current = v.erase( current ) ;
} else {
++ current ;
}
}
Alternativement, on pourrait écrire :
v.erase( std::remove( v.begin(), v.end(), val ), v.end() ) ;
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
|
|
| Back to top |
|
 |
Nicolas Guest
|
Posted: Tue Feb 24, 2004 11:50 am Post subject: Re: Vector et erase |
|
|
[snip]
| Quote: | ca dépend de l'implementation et du type d'objet pointé par
l'iterateur.
Pas du tout.
|
malheureusement, je confirme. Ca depend bien de l'implementation. J'ai eu
affaire avec des erase defini dans une STL, mais pas dans une autre (entre
BSDi et Sun par exemple), ou bien dont les arguments n'etaient pas dans le
meme ordre (et oui ...) ou encore ou la doc ne spécifié aucun retour alors
que l'implementationr retournait un iterateur.
quand au type d'objet pointé, c'est un abus de langage; je veux dire
vector, map, deque, list ... bref les objets qui implementent un erase non
pas tous le meme comportement.
[snip]
et si on veut garder un for, il suffit d'inverser la boucle .
bref ...
NB
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|