VoidSeer
Messages postés1Date d'inscriptionmercredi 12 octobre 2005StatutMembreDernière intervention12 octobre 2005 12 oct. 2005 à 14:42
Du classique ;-)
Pour approfondir le sujet, la meilleure référence AMA reste 'More Effective C++
de Scott Meyers, chez Addison-Wesley. Les items 28 et 29, traitent exactement de ce sujet, avec le code en prime.
Quelques remarques sur le code néanmoins :
- Quand on inclue des fichiers d'entête C, il est mieux d'utiliser ceux conçus
pour le C++, qui encapsulent les fonctions standard dans le namespace std.
Donc , et <stdlib.h> deviennent <cstdlib>, <cassert>
- On n'utilise pas NULL en C++, on utilise 0. Y'a une grande justification
derriere tout cela, assez technique d'ailleurs.
- Tester si un smart pointer est nul est un point délicat. L'implémentation
proposée ici utilise une fonction membre. C'est bien, cependant cela pose
un problème. Le Smart Pointer ne se comporte plus comme un pointeur.
Le principe d'une bonne implémentation de Smart Pointer est qu'il puisse se
substituer de manière transparente à un pointeur classique. Là ce n'est pas
le cas.
La solution proposée en général est d'implanter l'opérateur operator!.
Ce qui permet d'écrire:
if (!ptr) {/* Pointeur ou SmartPointer non null*/}
- Je ne vois pas l'intérêt de définir le destructeur comme virtuel. Au
contraire. La classe n'a pas a priori vocation à être surchargée, est ne
définir aucune fonction virtuelle fera l'économie de la création de la
vtable. Ce qui est plutot souhaitable pour une classe dont les instances
se substituent à un type scalaire.
BlackGoddess
Messages postés338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 juin 2005 15 févr. 2004 à 17:54
c'est du C, c'est protable C++ >> si tu savais les difficultés qu'on peut rencontrer en encapsulant du c dans du c++ ...
ok tibur :)
ds les lib boost il y a 5 smart pointers aussi pour ceux que ca interresse :)
www.boost.org
cs_tibur
Messages postés101Date d'inscriptionsamedi 9 février 2002StatutMembreDernière intervention 5 mai 2009 14 févr. 2004 à 20:06
> bah ... et alors ???
Je suis d'accord pour le debugging. Par contre tu ne peux pas redefinir l'operator = en C. Alors je vois pas l'interet de faire un smart pointer !
Peut etre que j'ai mal compris ta facon de faire ... Fait donc un post de ton code.
cs_tibur
Messages postés101Date d'inscriptionsamedi 9 février 2002StatutMembreDernière intervention 5 mai 2009 14 févr. 2004 à 20:01
> sinon c pas une copie de l'auto_ptr de la STL ca des fois ? :p
Nan : je viens de regarder comment marche le auto_ptr. Tu n'as pas de comptage de reference.
Je te fais un copier / coller de l'operateur = entre 2 auto_ptr :
Car p1 n'est plus valide. Avec ces SmartPointer, tu peux avoir plusieurs pointeurs pointant en meme temps sur le même objet.
cs_JCDjcd
Messages postés1138Date d'inscriptionmardi 10 juin 2003StatutMembreDernière intervention25 janvier 20094 14 févr. 2004 à 16:20
bah ... et alors ??? moi mes trucs font exatement la meme chose que ceux de cette source ! De plus ils contiennent plus d'infomration de debug, donc je ne foi pas ou est le probleme, surtout comme c'est du C, c'est protable C++ !!
BlackGoddess
Messages postés338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 juin 2005 14 févr. 2004 à 16:12
malloc c'est du C ... ici on parle de C++ => new
sinon c pas une copie de l'auto_ptr de la STL ca des fois ? :p
cs_JCDjcd
Messages postés1138Date d'inscriptionmardi 10 juin 2003StatutMembreDernière intervention25 janvier 20094 14 févr. 2004 à 13:53
bah en fait tu fais une surcouhe des malloc
a chaque fois que l'utilisateur alloue, tu coole avant sa strucutr une aute suture a toi (HEADER) qui contient les nombres de pointeues de reference, et de pluys je conserve le nom du fichier et la ligne de l'allocation, et aussi je chaine toute les allocation, comme cela a la fin de mon programme je liste toute les allocation qui n'ont pas ete allouees, et je sais lesquelles c'est !
Moi ca me debug tres bien.
cs_tibur
Messages postés101Date d'inscriptionsamedi 9 février 2002StatutMembreDernière intervention 5 mai 2009 14 févr. 2004 à 12:36
Essayes le code suivant :
class List {
public:
struct Node : public Counted{
SmartPointer<Node> prev, next;
~Node(){nb_inst--;}
Node(){nb_inst++;}
static int nb_inst;
};
SmartPointer<Node> root;
static void test(){
{
List l;
l.root = new Node();
l.root->next = new Node();
l.root->next->prev = l.root;
l.root->next->next = new Node();
l.root->next->next->prev = l.root->next;
}
assert(Node::nb_inst==0);
}
};
int List::Node::nb_inst = 0;
Bon, bien, sur si tu remet à NULL tout les prev, ca revient dans l'ordre ...
Petite question, tout de meme : si c'est pas des classes, que tu utilises, c'est quoi alors ?
cs_JCDjcd
Messages postés1138Date d'inscriptionmardi 10 juin 2003StatutMembreDernière intervention25 janvier 20094 14 févr. 2004 à 08:51
heu excuse moi, mais moi aussi j'utilise les compteur de reference dans mes allocation, seulement ce n'est pas des classes.
Mais le probleme des liste chainees marchge tres tres bien, moi je ne voix pas pourquoi ca ne marcherai pas, et comme c'est lez cas, ce n'est pas normal.
12 oct. 2005 à 14:42
Pour approfondir le sujet, la meilleure référence AMA reste 'More Effective C++
de Scott Meyers, chez Addison-Wesley. Les items 28 et 29, traitent exactement de ce sujet, avec le code en prime.
Quelques remarques sur le code néanmoins :
- Quand on inclue des fichiers d'entête C, il est mieux d'utiliser ceux conçus
pour le C++, qui encapsulent les fonctions standard dans le namespace std.
Donc , et <stdlib.h> deviennent <cstdlib>, <cassert>
- On n'utilise pas NULL en C++, on utilise 0. Y'a une grande justification
derriere tout cela, assez technique d'ailleurs.
- Tester si un smart pointer est nul est un point délicat. L'implémentation
proposée ici utilise une fonction membre. C'est bien, cependant cela pose
un problème. Le Smart Pointer ne se comporte plus comme un pointeur.
Le principe d'une bonne implémentation de Smart Pointer est qu'il puisse se
substituer de manière transparente à un pointeur classique. Là ce n'est pas
le cas.
La solution proposée en général est d'implanter l'opérateur operator!.
Ce qui permet d'écrire:
if (!ptr) {/* Pointeur ou SmartPointer non null*/}
- Je ne vois pas l'intérêt de définir le destructeur comme virtuel. Au
contraire. La classe n'a pas a priori vocation à être surchargée, est ne
définir aucune fonction virtuelle fera l'économie de la création de la
vtable. Ce qui est plutot souhaitable pour une classe dont les instances
se substituent à un type scalaire.
15 févr. 2004 à 17:54
ok tibur :)
ds les lib boost il y a 5 smart pointers aussi pour ceux que ca interresse :)
www.boost.org
14 févr. 2004 à 20:06
Je suis d'accord pour le debugging. Par contre tu ne peux pas redefinir l'operator = en C. Alors je vois pas l'interet de faire un smart pointer !
Peut etre que j'ai mal compris ta facon de faire ... Fait donc un post de ton code.
14 févr. 2004 à 20:01
Nan : je viens de regarder comment marche le auto_ptr. Tu n'as pas de comptage de reference.
Je te fais un copier / coller de l'operateur = entre 2 auto_ptr :
auto_ptr<_Ty>& operator=(auto_ptr_ref<_Ty>& _Right) throw ()
{ // assign compatible _Right._Ref (assume pointer)
reset(_Right._Ref.release());
return (*this);
}
Il fait un release sur le auto_ptr right. Ca veut dire que ce code plante :
typedef std::auto_ptr<double> DoublePtr;
DoublePtr p1(new double(5.0));
DoublePtr p2 = p1;
std::cout << *p1 <<std::endl;
Car p1 n'est plus valide. Avec ces SmartPointer, tu peux avoir plusieurs pointeurs pointant en meme temps sur le même objet.
14 févr. 2004 à 16:20
14 févr. 2004 à 16:12
sinon c pas une copie de l'auto_ptr de la STL ca des fois ? :p
14 févr. 2004 à 13:53
a chaque fois que l'utilisateur alloue, tu coole avant sa strucutr une aute suture a toi (HEADER) qui contient les nombres de pointeues de reference, et de pluys je conserve le nom du fichier et la ligne de l'allocation, et aussi je chaine toute les allocation, comme cela a la fin de mon programme je liste toute les allocation qui n'ont pas ete allouees, et je sais lesquelles c'est !
Moi ca me debug tres bien.
14 févr. 2004 à 12:36
class List {
public:
struct Node : public Counted{
SmartPointer<Node> prev, next;
~Node(){nb_inst--;}
Node(){nb_inst++;}
static int nb_inst;
};
SmartPointer<Node> root;
static void test(){
{
List l;
l.root = new Node();
l.root->next = new Node();
l.root->next->prev = l.root;
l.root->next->next = new Node();
l.root->next->next->prev = l.root->next;
}
assert(Node::nb_inst==0);
}
};
int List::Node::nb_inst = 0;
Bon, bien, sur si tu remet à NULL tout les prev, ca revient dans l'ordre ...
Petite question, tout de meme : si c'est pas des classes, que tu utilises, c'est quoi alors ?
14 févr. 2004 à 08:51
Mais le probleme des liste chainees marchge tres tres bien, moi je ne voix pas pourquoi ca ne marcherai pas, et comme c'est lez cas, ce n'est pas normal.