C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Fonction qui supprime les pointeurs d'un container
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Michael
Guest





PostPosted: Thu Jan 13, 2005 5:18 pm    Post subject: Fonction qui supprime les pointeurs d'un container Reply with quote



Bonjour à tous,

dans "Le Language C++" de Stroustrup, il donne l'utilisation suivante de
std::transform:

//H
class foo
{
private:
int i;
public:
foo(int index) : i(index) {}
};

template<class T> T* delete_ptr(T* p)
{
delete p;
return 0;
}

//CPP
std::vector<foo *> v;
v.push_back(new foo(0));
v.push_back(new foo(1));
v.push_back(new foo(2));
v.push_back(new foo(3));

std::transform(v.begin(),v.end(),v.begin(),delete_ptr<foo>);

qui permet de supprimer tous les pointeurs du container...

J'ai créé une fonction Purge à laquelle on passe un vecteur contenant des
pointeurs, et qui fait le transform tout seul.

template<class T> void Purge(std::vector<T*> & liste)
{
std::transform(liste.begin(),liste.end(),liste.begin(),delete_ptr<T>);
}

J'aimerai savoir si pour supporter n'importe quel container il faut que je
fasse une surcharge par container, ou bien si en passant par les template
ça peut se faire, mais j'avoue être un peu charette là dessus...

Comment feriez-vous une telle chose?
Back to top
xavier
Guest





PostPosted: Thu Jan 13, 2005 5:38 pm    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote



Michael a dit le 13/01/2005 18:18:
Quote:
J'aimerai savoir si pour supporter n'importe quel container il faut que je
fasse une surcharge par container, ou bien si en passant par les template
ça peut se faire, mais j'avoue être un peu charette là dessus...

Comment feriez-vous une telle chose?

template <typename T, template
void Purge(Container<T*> & liste) {
std::transform(liste.begin(),liste.end(),liste.begin(),delete_ptr<T>);
}

xavier

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Jan 14, 2005 8:16 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote



Michael wrote:

Quote:
dans "Le Language C++" de Stroustrup, il donne l'utilisation suivante
de
std::transform:

//H
class foo
{
private:
int i;
public:
foo(int index) : i(index) {}
};

template<class T> T* delete_ptr(T* p)
{
delete p;
return 0;
}

//CPP
std::vector<foo *> v;
v.push_back(new foo(0));
v.push_back(new foo(1));
v.push_back(new foo(2));
v.push_back(new foo(3));

std::transform(v.begin(),v.end(),v.begin(),delete_ptr<foo>);

qui permet de supprimer tous les pointeurs du container...

Et qui donne un comportement indéfini.

AMHA, ce n'est pas un bon exemple, pour plusieurs raisons.
D'abord, formellement, il donne un comportement indéfini. Dans
la pratique, ce comportement indéfini ne fait jamais de
problème, et est sans importance, dans la mésure où le cible de
transform est la même collection que la source. Dans d'autres
cas, en revanche, on a bien une collection qui contient des
pointeurs supprimés, et donc, la risque d'un comportement
indéfini est élevée. Si on tient à ce que la destination et la
source soient identique, on ne se sert pas de transform, mais de
for_each, et delete_ptr serait plutôt :

template< typename T >
struct delete_ptr
{
void operator()( T*& p )
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;

Quote:
J'ai créé une fonction Purge à laquelle on passe un vecteur
contenant des pointeurs, et qui fait le transform tout seul.

template<class T> void Purge(std::vector<T*> & liste)
{

std::transform(liste.begin(),liste.end(),liste.begin(),delete_ptr<T>);
}

J'aimerai savoir si pour supporter n'importe quel container il
faut que je fasse une surcharge par container, ou bien si en
passant par les template ça peut se faire, mais j'avoue être
un peu charette là dessus...

Comment feriez-vous une telle chose?

Avec un template sur le type de la collection :

template< typename Container >
void
purge( Container& c )
{
typedef Container::value_type Ptr ;
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ;
std::for_each( c.begin(), c.end(),
delete_ptr< boost::remove_pointer< Ptr >::type >() ) ;
}

(Enfin, c'est ce que j'aimerais faire. Pour l'instant, je suis
obligé à me servir d'un compilateur qui ne supporte pas Boost.)

--
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


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Jan 14, 2005 8:20 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Michael wrote:

Quote:
dans "Le Language C++" de Stroustrup, il donne l'utilisation suivante
de
std::transform:

//H
class foo
{
private:
int i;
public:
foo(int index) : i(index) {}
};

template<class T> T* delete_ptr(T* p)
{
delete p;
return 0;
}

//CPP
std::vector<foo *> v;
v.push_back(new foo(0));
v.push_back(new foo(1));
v.push_back(new foo(2));
v.push_back(new foo(3));

std::transform(v.begin(),v.end(),v.begin(),delete_ptr<foo>);

qui permet de supprimer tous les pointeurs du container...

Et qui donne un comportement indéfini.

AMHA, ce n'est pas un bon exemple, pour plusieurs raisons.
D'abord, formellement, il donne un comportement indéfini. Dans
la pratique, ce comportement indéfini ne fait jamais de
problème, et est sans importance, dans la mésure où le cible de
transform est la même collection que la source. Dans d'autres
cas, en revanche, on a bien une collection qui contient des
pointeurs supprimés, et donc, la risque d'un comportement
indéfini est élevée. Si on tient à ce que la destination et la
source soient identique, on ne se sert pas de transform, mais de
for_each, et delete_ptr serait plutôt :

template< typename T >
struct delete_ptr
{
void operator()( T*& p )
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;

Quote:
J'ai créé une fonction Purge à laquelle on passe un vecteur
contenant des pointeurs, et qui fait le transform tout seul.

template<class T> void Purge(std::vector<T*> & liste)
{

std::transform(liste.begin(),liste.end(),liste.begin(),delete_ptr<T>);
}

J'aimerai savoir si pour supporter n'importe quel container il
faut que je fasse une surcharge par container, ou bien si en
passant par les template ça peut se faire, mais j'avoue être
un peu charette là dessus...

Comment feriez-vous une telle chose?

Avec un template sur le type de la collection :

template< typename Container >
void
purge( Container& c )
{
typedef Container::value_type Ptr ;
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ;
std::for_each( c.begin(), c.end(),
delete_ptr< boost::remove_pointer< Ptr >::type >() ) ;
}

(Enfin, c'est ce que j'aimerais faire. Pour l'instant, je suis
obligé à me servir d'un compilateur qui ne supporte pas Boost.)

--
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


Back to top
Michael
Guest





PostPosted: Tue Jan 18, 2005 1:12 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Pourais tu m'expliquer ce code s'il te plait, je ne comprends pas tout:

Quote:
template< typename T
struct delete_ptr
{
void operator()( T*& p )
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;

Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un temporaire?

Quote:
template< typename Container
void
purge( Container& c )
{
typedef Container::value_type Ptr ;
Ici je ne connais pas, mais je suppose que Container::value_type correspond

au type d'objets contenus par Container??? (ici un pointeur?)

Quote:
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ;
Je ne suis pas familier des asserts, mais je suppose que c'est pour

vérifier que le contenu du container est bien un pointeur

Quote:
std::for_each( c.begin(), c.end(),
delete_ptr< boost::remove_pointer< Ptr >::type >() ) ;

Pourquoi enlever le pointeur ici? A quoi correspond ::type?

Quote:
}

Merci d'avance!

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Jan 18, 2005 8:11 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Michael wrote:
Quote:
Pourais tu m'expliquer ce code s'il te plait, je ne comprends
pas tout:

template< typename T
struct delete_ptr
{
void operator()( T*& p )

(Il faudrait y ajouter un const que j' ai oublie.)

Quote:
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;

Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un
temporaire?

Parce que techniquement, faire un delete sur un pointeur qui est
contenu dans une collection standard a un comportement
indéfini. Donc, on met le pointeur dans un temporaire, on
remplace avec null dans la collection, et seulement alors on
fait le delete.

Certains aime l'idiome avec swap :

Quote:
template< typename T
struct delete_ptr
{
void operator()( T*& p ) const
{
T* tmp = NULL ;
std::swap( tmp, p ) ;
delete tmp ;
}
} ;

Personnellement, je ne vois pas d'avantage par rapport à ma
version initiale, sauf que c'est plus in.

Quote:
template< typename Container
void
purge( Container& c )
{
typedef Container::value_type Ptr ;

Ici je ne connais pas, mais je suppose que
Container::value_type correspond au type d'objets contenus par
Container??? (ici un pointeur?)

Tout à fait. Je dirais que l'utilisation de tous ces typedef's,
c'est la véritable innovation de la STL. À apprendre -- ça
t'étonnerait à quel point c'est utile.

Quote:
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ;

Je ne suis pas familier des asserts, mais je suppose que c'est
pour vérifier que le contenu du container est bien un pointeur

C'est du Boost (aussi à apprendre). BOOST_STATIC_ASSERT, c'est
un assert qui déclenche lors de la compilation. C-à-d ici is Ptr
n'est pas un pointeur, on aurait une erreur de compilation.

Quote:
std::for_each( c.begin(), c.end(),
delete_ptr< boost::remove_pointer< Ptr >::type >() ) ;

Pourquoi enlever le pointeur ici? A quoi correspond ::type?

Encore : boost::remove_ptr est une classe générique avec un
typedef d'un type qui s'appelle type. Si la type d'instanciation
est un pointeur, le typedef est le type sans le pointeur.

Quote:
}

Écrire des choses comme remove_pointer, etc., n'est pas
trivial. Il y a beaucoup de chose à apprendre avant. Les
utiliser, en revanche, n'est pas si compliquer, et vaut la
peine, même si on n'est pas très avancé. (À vrai dire, je ne
crois pas que remove_pointer en soi soit si difficile. Mais
l'ensemble dont il fait partie utilise des techniques qu'il faut
bien qualifier d'avancées.)

--
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


Back to top
Michael
Guest





PostPosted: Tue Jan 18, 2005 10:47 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Merci pour toutes ces explications... Néanmoins il y a encore quelque chose
que je ne comprends pas:

Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur
directement? Le comportement indéfini auquel tu fais allusion en est-il la
seule explication?
Back to top
Michael
Guest





PostPosted: Tue Jan 18, 2005 11:18 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

xavier <xtrochu (AT) yahoo (DOT) com> wrote in
news:41ecee27$0$7832$636a15ce (AT) news (DOT) free.fr:

Quote:
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et pas le
pointeur directement? Le comportement indéfini auquel tu fais
allusion en est-il la seule explication?

Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut
le passer par référence.

Alors pourquoi mon premier exemple tiré du bouquin compilait sans
problèmes?

Back to top
xavier
Guest





PostPosted: Tue Jan 18, 2005 11:21 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Michael a dit le 18/01/2005 11:47:
Quote:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur
directement? Le comportement indéfini auquel tu fais allusion en est-il la
seule explication?

Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut
le passer par référence.

Par contre, j'aimerais savoir en quoi un pointeur invalide dans un
conteneur est un comportement indéfini. A priori, je pensais que le
conteneur lui-même ne pouvait manipuler que les pointeurs, et pas les
déréférencer... La manipulation de pointeur invalide est-elle un
comportement indéfini, tout simplement, ou y a-t-il une raison plus
complexe ?

xavier

Back to top
Michael
Guest





PostPosted: Tue Jan 18, 2005 11:30 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

OK, c'est très clair maintenant...

Du coup j'en profite pour poser une autre question :-D

*dest++ = operation(*it);

Dans l'ordre, c'est affectation puis incrémentation?

J'imagine que c'est l'inverse si on choisit une pré-incrémentation?
Back to top
xavier
Guest





PostPosted: Tue Jan 18, 2005 11:40 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Michael a dit le 18/01/2005 12:18:
Quote:
Alors pourquoi mon premier exemple tiré du bouquin compilait sans
problèmes?

L'utilisation était très différente.

std::transform() et std::for_each() ne font pas du tout la même chose.

Dans l'esprit, std::transform() fait :

transform(begin, end, dest, operation) {
for(it = begin, it != end; ++it)
*dest++ = operation(*it);
}

et std::for_each() fait :

for_each(begin, end, operation) {
for(it = begin; it != end; ++it)
operation(*it);
}

xavier

Back to top
Michael
Guest





PostPosted: Tue Jan 18, 2005 11:51 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Quote:
En cherchant un peu :
http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/stl__algo_8h-sou
rce.html#l00778

Merci pour le lien

Quote:
Tu verras que l'implémentation de libstdc++ ne correspond pas tout à
fait à celle que j'ai indiquée.

J'imagine que c'est l'inverse si on choisit une pré-incrémentation?

Oui.

xavier

Merci pour tes réponses

Back to top
xavier
Guest





PostPosted: Tue Jan 18, 2005 11:54 am    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

Michael a dit le 18/01/2005 12:30:
Quote:
*dest++ = operation(*it);

Dans l'ordre, c'est affectation puis incrémentation?

Oui.

En cherchant un peu :
http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/stl__algo_8h-source.html#l00778

Tu verras que l'implémentation de libstdc++ ne correspond pas tout à
fait à celle que j'ai indiquée.

Quote:
J'imagine que c'est l'inverse si on choisit une pré-incrémentation?

Oui.

xavier

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Jan 18, 2005 3:10 pm    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

xavier wrote:
Quote:
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et
pas le pointeur directement? Le comportement indéfini auquel
tu fais allusion en est-il la seule explication?

Pour pouvoir modifier la valeur du pointeur dans le conteneur,
il faut le passer par référence.

Par contre, j'aimerais savoir en quoi un pointeur invalide
dans un conteneur est un comportement indéfini. A priori, je
pensais que le conteneur lui-même ne pouvait manipuler que les
pointeurs, et pas les déréférencer... La manipulation de
pointeur invalide est-elle un comportement indéfini, tout
simplement, ou y a-t-il une raison plus complexe ?

À peu près tout ce que on peut faire avec un pointeur invalide,
c'est de lui affecter une nouvelle valeur. Même lire simplement
le pointeur est un comportement indéfini. En termes de la norme,
on ne peut pas le copier, et la norme dit qu'il faut que tous
les éléments dans une collection standard soient copiables.

Dans la pratique, c'est fort peu probable que tu aurais des
problèmes.

--
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


Back to top
xavier
Guest





PostPosted: Tue Jan 18, 2005 3:40 pm    Post subject: Re: Fonction qui supprime les pointeurs d'un container Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] a dit le 18/01/2005 16:10:
Quote:
À peu près tout ce que on peut faire avec un pointeur invalide,
c'est de lui affecter une nouvelle valeur. Même lire simplement
le pointeur est un comportement indéfini. En termes de la norme,
on ne peut pas le copier, et la norme dit qu'il faut que tous
les éléments dans une collection standard soient copiables.

Merci pour cette clarification.

xavier

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.