Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Jean-Marc Bourguet
"laurent" writes:
salut,
alors voila, jai fais un algo pour supprimer des elements d'un std::vector :
varvector::iterator i = variablelist.begin(); while (1) { variable *v = *i; if (v->bloc >= bloc) { delete v; variablelist.erase(i); } if (i == variablelist.end()) break; }
ya mieux?
Oui.
Ton iterateur devient invalide a la premiere iteration.
Mets la condition dans le while, c'est plus robuste dans le cas ou la liste est vide.
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
"laurent" <qsdqd@sss.ss> writes:
salut,
alors voila, jai fais un algo pour supprimer des elements d'un std::vector :
varvector::iterator i = variablelist.begin();
while (1)
{
variable *v = *i;
if (v->bloc >= bloc) {
delete v;
variablelist.erase(i);
}
if (i == variablelist.end()) break;
}
ya mieux?
Oui.
Ton iterateur devient invalide a la premiere iteration.
Mets la condition dans le while, c'est plus robuste dans le cas ou la
liste est vide.
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
alors voila, jai fais un algo pour supprimer des elements d'un std::vector :
varvector::iterator i = variablelist.begin(); while (1) { variable *v = *i; if (v->bloc >= bloc) { delete v; variablelist.erase(i); } if (i == variablelist.end()) break; }
ya mieux?
Oui.
Ton iterateur devient invalide a la premiere iteration.
Mets la condition dans le while, c'est plus robuste dans le cas ou la liste est vide.
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
Falk Tannhäuser
laurent wrote:
varvector::iterator i = variablelist.begin(); while (1) { variable *v = *i; if (v->bloc >= bloc) { delete v; variablelist.erase(i); } if (i == variablelist.end()) break; }
Les problèmes : - erase(i) invalide l'itérateur i, donc tu n'as plus le droit de te servir de sa valeur, - quand tu ne supprimes pas l'élément pointé par i, i n'avance pas => boucle infinie, - si le vecteur est vide, ça se passe mal car tu essayes toucher à des éléments inexistants - mieux vaut placer le test à l'ent rée de la boucle.
Voici ce que je propose (ma boule de cristal me dit que 'varvector' est un typedef pour 'std::vector<variable*>', que 'variable' est une struct contenant un champ 'bloc' et qu'on est sûr que les pointeurs contenus dans 'variablelist' pointent tous sur des objets valides) :
for(varvector::iterator it = variablelist.begin(); it != variablel ist.end(); ) { variable* pv = *it; if(pv->bloc >= bloc) { *it = 0; // Pour être sûr de ne jamais avoir de pointeur inv alide dans le vecteur delete pv; it = v.erase(it); }else ++it; }
Falk
laurent wrote:
varvector::iterator i = variablelist.begin();
while (1)
{
variable *v = *i;
if (v->bloc >= bloc) {
delete v;
variablelist.erase(i);
}
if (i == variablelist.end()) break;
}
Les problèmes :
- erase(i) invalide l'itérateur i, donc tu n'as plus le droit
de te servir de sa valeur,
- quand tu ne supprimes pas l'élément pointé par i, i n'avance pas
=> boucle infinie,
- si le vecteur est vide, ça se passe mal car tu essayes toucher
à des éléments inexistants - mieux vaut placer le test à l'ent rée
de la boucle.
Voici ce que je propose (ma boule de cristal me dit que 'varvector'
est un typedef pour 'std::vector<variable*>', que 'variable' est
une struct contenant un champ 'bloc' et qu'on est sûr que les
pointeurs contenus dans 'variablelist' pointent tous sur des objets
valides) :
for(varvector::iterator it = variablelist.begin(); it != variablel ist.end(); )
{
variable* pv = *it;
if(pv->bloc >= bloc)
{
*it = 0; // Pour être sûr de ne jamais avoir de pointeur inv alide dans le vecteur
delete pv;
it = v.erase(it);
}else
++it;
}
varvector::iterator i = variablelist.begin(); while (1) { variable *v = *i; if (v->bloc >= bloc) { delete v; variablelist.erase(i); } if (i == variablelist.end()) break; }
Les problèmes : - erase(i) invalide l'itérateur i, donc tu n'as plus le droit de te servir de sa valeur, - quand tu ne supprimes pas l'élément pointé par i, i n'avance pas => boucle infinie, - si le vecteur est vide, ça se passe mal car tu essayes toucher à des éléments inexistants - mieux vaut placer le test à l'ent rée de la boucle.
Voici ce que je propose (ma boule de cristal me dit que 'varvector' est un typedef pour 'std::vector<variable*>', que 'variable' est une struct contenant un champ 'bloc' et qu'on est sûr que les pointeurs contenus dans 'variablelist' pointent tous sur des objets valides) :
for(varvector::iterator it = variablelist.begin(); it != variablel ist.end(); ) { variable* pv = *it; if(pv->bloc >= bloc) { *it = 0; // Pour être sûr de ne jamais avoir de pointeur inv alide dans le vecteur delete pv; it = v.erase(it); }else ++it; }
Falk
Fabien LE LEZ
On Wed, 17 Nov 2004 19:44:15 +0100, Falk Tannhäuser :
it = v.erase(it);
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu des compilos qui ne suivent pas la norme sur ce point.
Pour ce genre de compilo foireux :
for (int i=0; i<variablelist.size();) { if (variablelist[i]->bloc >= bloc) { variablelist.erase (variablelist.begin()+i); } else { ++i; } }
Tant qu'on garde std::vector<>, cette façon de procéder ne me paraît pas une complète hérésie -- après tout, vector<> est optimisé pour l'accès aléatoire.
-- ;-)
On Wed, 17 Nov 2004 19:44:15 +0100, Falk Tannhäuser
<falk.tannhauser@crf.canon.fr>:
it = v.erase(it);
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu
des compilos qui ne suivent pas la norme sur ce point.
Pour ce genre de compilo foireux :
for (int i=0; i<variablelist.size();)
{
if (variablelist[i]->bloc >= bloc)
{
variablelist.erase (variablelist.begin()+i);
}
else
{
++i;
}
}
Tant qu'on garde std::vector<>, cette façon de procéder ne me paraît
pas une complète hérésie -- après tout, vector<> est optimisé pour
l'accès aléatoire.
On Wed, 17 Nov 2004 19:44:15 +0100, Falk Tannhäuser :
it = v.erase(it);
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu des compilos qui ne suivent pas la norme sur ce point.
Pour ce genre de compilo foireux :
for (int i=0; i<variablelist.size();) { if (variablelist[i]->bloc >= bloc) { variablelist.erase (variablelist.begin()+i); } else { ++i; } }
Tant qu'on garde std::vector<>, cette façon de procéder ne me paraît pas une complète hérésie -- après tout, vector<> est optimisé pour l'accès aléatoire.
-- ;-)
Falk Tannhäuser
Fabien LE LEZ wrote:
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu des compilos qui ne suivent pas la norme sur ce point.
Il existe aussi la solution basée sur std::remove_if() - mais malheureusement, elle ne permet pas à ma connaissance de 'deleter' les objets pointés lorsqu'on l'utilise pour enlever des pointeurs "nus" du vecteur. Si 'varvector' était un 'std::vector<variable>' ou un 'std::vector<boost::shared_ptr<variable> >', cela ne poserait pas de problème, une fois défini le foncteur qui va bien : __________________________________________________________________________ template<typename ClassT, typename MemT, template<typename> class CmpFunc> class member_comparator_helper { MemT ClassT::* pmem; MemT value; public: member_comparator_helper(MemT ClassT::* pm, MemT const& v) : pmem(pm), value(v) {}
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu
des compilos qui ne suivent pas la norme sur ce point.
Il existe aussi la solution basée sur std::remove_if() - mais malheureusement,
elle ne permet pas à ma connaissance de 'deleter' les objets pointés lorsqu'on
l'utilise pour enlever des pointeurs "nus" du vecteur. Si 'varvector' était un
'std::vector<variable>' ou un 'std::vector<boost::shared_ptr<variable> >',
cela ne poserait pas de problème, une fois défini le foncteur qui va bien :
__________________________________________________________________________
template<typename ClassT, typename MemT, template<typename> class CmpFunc>
class member_comparator_helper
{
MemT ClassT::* pmem;
MemT value;
public:
member_comparator_helper(MemT ClassT::* pm, MemT const& v) : pmem(pm), value(v) {}
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu des compilos qui ne suivent pas la norme sur ce point.
Il existe aussi la solution basée sur std::remove_if() - mais malheureusement, elle ne permet pas à ma connaissance de 'deleter' les objets pointés lorsqu'on l'utilise pour enlever des pointeurs "nus" du vecteur. Si 'varvector' était un 'std::vector<variable>' ou un 'std::vector<boost::shared_ptr<variable> >', cela ne poserait pas de problème, une fois défini le foncteur qui va bien : __________________________________________________________________________ template<typename ClassT, typename MemT, template<typename> class CmpFunc> class member_comparator_helper { MemT ClassT::* pmem; MemT value; public: member_comparator_helper(MemT ClassT::* pm, MemT const& v) : pmem(pm), value(v) {}
Ce qui devrait régler tout problème d'itérateur et de limite de boucle.
-Eric
merci d'avance
kanze
Falk Tannhäuser wrote in message news:<419bce21$0$5179$...
Fabien LE LEZ wrote:
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu des compilos qui ne suivent pas la norme sur ce point.
Il existe aussi la solution basée sur std::remove_if() - mais malheureusement, elle ne permet pas à ma connaissance de 'deleter' les objets pointés lorsqu'on l'utilise pour enlever des pointeurs "nus" du vecteur. Si 'varvector' était un 'std::vector<variable>' ou un 'std::vector<boost::shared_ptr<variable> >', cela ne poserait pas de problème, une fois défini le foncteur qui va bien : k
En fait, je crois qu'on a ici un cas où la sémantique de remove_if est exactement ce qu'il faut :
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Falk Tannhäuser <tannhauser86549spam@free.fr> wrote in message
news:<419bce21$0$5179$636a15ce@news.free.fr>...
Fabien LE LEZ wrote:
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu
des compilos qui ne suivent pas la norme sur ce point.
Il existe aussi la solution basée sur std::remove_if() - mais
malheureusement, elle ne permet pas à ma connaissance de 'deleter' les
objets pointés lorsqu'on l'utilise pour enlever des pointeurs "nus" du
vecteur. Si 'varvector' était un 'std::vector<variable>' ou un
'std::vector<boost::shared_ptr<variable> >', cela ne poserait pas de
problème, une fois défini le foncteur qui va bien : k
En fait, je crois qu'on a ici un cas où la sémantique de remove_if est
exactement ce qu'il faut :
Falk Tannhäuser wrote in message news:<419bce21$0$5179$...
Fabien LE LEZ wrote:
S'assurer avant que vector<>::erase renvoie bien un itérateur. J'ai vu des compilos qui ne suivent pas la norme sur ce point.
Il existe aussi la solution basée sur std::remove_if() - mais malheureusement, elle ne permet pas à ma connaissance de 'deleter' les objets pointés lorsqu'on l'utilise pour enlever des pointeurs "nus" du vecteur. Si 'varvector' était un 'std::vector<variable>' ou un 'std::vector<boost::shared_ptr<variable> >', cela ne poserait pas de problème, une fois défini le foncteur qui va bien : k
En fait, je crois qu'on a ici un cas où la sémantique de remove_if est exactement ce qu'il faut :
|> Il me semble que le contenu entre "pivot" et "end()" n'est pas |> garanti. A moins que ça ait changé entre-temps ?
Bien vu. Je crois que tu as raison. Ce qu'il faudrait faire, c'est d'effectuer les delete d'abord, en mettant le pointeur à null, puis faire le replace/erase.
-- James Kanze Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Fabien LE LEZ <gramster@gramster.com> writes:
|> On 18 Nov 2004 23:52:49 -0800, kanze@gabi-soft.fr:
|> Il me semble que le contenu entre "pivot" et "end()" n'est pas
|> garanti. A moins que ça ait changé entre-temps ?
Bien vu. Je crois que tu as raison. Ce qu'il faudrait faire, c'est
d'effectuer les delete d'abord, en mettant le pointeur à null, puis
faire le replace/erase.
--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
|> Il me semble que le contenu entre "pivot" et "end()" n'est pas |> garanti. A moins que ça ait changé entre-temps ?
Bien vu. Je crois que tu as raison. Ce qu'il faudrait faire, c'est d'effectuer les delete d'abord, en mettant le pointeur à null, puis faire le replace/erase.
-- James Kanze Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Fabien LE LEZ
On 21 Nov 2004 15:15:38 +0100, James Kanze :
Ce qu'il faudrait faire, c'est d'effectuer les delete d'abord, en mettant le pointeur à null, puis faire le
replace
"remove" ici, non ?
/erase.
Mais ça oblige à faire deux fois le test. Or il n'est pas forcément faisable après le delete.
-- ;-)
On 21 Nov 2004 15:15:38 +0100, James Kanze <james.kanze@free.fr>:
Ce qu'il faudrait faire, c'est
d'effectuer les delete d'abord, en mettant le pointeur à null, puis
faire le
replace
"remove" ici, non ?
/erase.
Mais ça oblige à faire deux fois le test. Or il n'est pas forcément
faisable après le delete.
Ce qu'il faudrait faire, c'est d'effectuer les delete d'abord, en mettant le pointeur à null, puis faire le
replace
"remove" ici, non ?
/erase.
Mais ça oblige à faire deux fois le test. Or il n'est pas forcément faisable après le delete.
-- ;-)
kanze
Fabien LE LEZ wrote in message news:...
On 21 Nov 2004 15:15:38 +0100, James Kanze :
Ce qu'il faudrait faire, c'est d'effectuer les delete d'abord, en mettant le pointeur à null, puis faire le
replace
"remove" ici, non ?
Oui.
/erase.
Mais ça oblige à faire deux fois le test. Or il n'est pas forcément faisable après le delete.
Ça oblige à faire deux tests différents. Dans la première passe, le test sur la condition, pour savoir s'il faut faire delete ou non, et la deuxième passe, sur null.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ <gramster@gramster.com> wrote in message
news:<0qe1q0ho9ons66psm0kjbstqouhhn7ov2u@4ax.com>...
On 21 Nov 2004 15:15:38 +0100, James Kanze <james.kanze@free.fr>:
Ce qu'il faudrait faire, c'est
d'effectuer les delete d'abord, en mettant le pointeur à null, puis
faire le
replace
"remove" ici, non ?
Oui.
/erase.
Mais ça oblige à faire deux fois le test. Or il n'est pas forcément
faisable après le delete.
Ça oblige à faire deux tests différents. Dans la première passe, le test
sur la condition, pour savoir s'il faut faire delete ou non, et la
deuxième passe, sur null.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Ce qu'il faudrait faire, c'est d'effectuer les delete d'abord, en mettant le pointeur à null, puis faire le
replace
"remove" ici, non ?
Oui.
/erase.
Mais ça oblige à faire deux fois le test. Or il n'est pas forcément faisable après le delete.
Ça oblige à faire deux tests différents. Dans la première passe, le test sur la condition, pour savoir s'il faut faire delete ou non, et la deuxième passe, sur null.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34