Non plus. J'ai tapé le truc à la va-vite car je voulais surtout mettre en évidence l'idiome copy-swap (ce à quoi j'ai magnifiquement échoué parce que j'ai mis un const de trop)...
J'ai corrigé, et je viens d'en profiter pour rajouter un constructeur par défaut.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
On ne peut pas copier un CSmartPointer défaut-initialisé :
déréférence un pointeur nul!
Code : Sélectionner tout - Visualiser dans une fenêtre à part CSmartPointer<int> p (CSmartPointer ());
re-re-re-corrigé!
Dis, quand on aura fini, on pourra supprimer les postes de corrections ? Ils me dépriment un peu...
(d'un autre côté, je n'ai jamais voulu cacher que c'était codé sur le pouce)
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Oui, j'y avais pensé.
Pourquoi (void)? Pourquoi pas ()?
Code : Sélectionner tout - Visualiser dans une fenêtre à part CSmartPointer(void)
Pourquoi pas d'init-list?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 explicit CSmartPointer(T *p) { this->p = p; this->pr = new int(1); }
- L'habitude de la différence entre () et (void) en C, je préfère mettre systématiquement (void).
- Et donc, ça, ça marche, ça compilera et ça fera exactement ce qu'on veut que ça fasse ? (hormis le contrôle sur les exceptions)
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 explicit CSmartPointer(T *p) : p(p), pr(new int(1)) { }
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Je ne sais pas pourquoi mais j'avais en tête que ce n'étais pas possible, j'ai du le vérifier pour le croireEnvoyé par corrector
, mais au final je suppose qu'il est quand même plus clair d'avoir deux noms différents et ça ne coute pas bien cher non... (enfin je suppose que c'est une question de choix personel)...?
Je ne suis pas sûr de tout saisir (Envoyé par corrector
), quelle serait le code adapté alors... :
Dans ce cas précis, la gestion d'un bloc catch_try ne coûte pas trop cher en terme de performance?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 CSmartPointer(T *_p) : p(_p) { try{ this->pr = new int(1); } catch(bad_alloc &) { delete p; throw; } }
Juste par curiosité, dans quelle cas ce genre d'exception arrive en général (je n'ai jamais été confronté à ce problème)?
Et tant qu'à faire, n'est-il pas préférable d'éviter les exceptions justement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 CSmartPointer(T *_p) : p(_p), pr(new(nothrow) int(1)) { }
Dans un constructeur, pas trop.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Je retire ce que j'ai dit sur le nothrow () la suite de mon code est basé sur un compteur sencé être alloué correctement donc... voila le code complet de ma classe :
Et l'implémentation :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 template <class T> class CSmartPointer { public: CSmartPointer(T *Pointer = NULL); CSmartPointer(CSmartPointer<T> const &SmartPointer); ~CSmartPointer(); CSmartPointer<T> & operator = (CSmartPointer<T> const &SmartPointer); CSmartPointer<T> & operator = (T *Pointer); bool operator () (); T const * const operator -> () const; T * const operator -> (); T const & operator * () const; T & operator * (); operator T const * const() const; operator T * const(); void Swap(CSmartPointer<T> &SmartPointer); template <class Other> operator CSmartPointer<Other>() const; private: T *m_Pointer; // Pointer on the object int *m_Counter; // Counter on the object pointed };Je ne suis pas encore bien habitué au mot clé explicit mais dans mon projet j'utilise :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 template <class T> inline CSmartPointer<T>::CSmartPointer(T *Pointer) : m_Pointer(Pointer), m_Counter(NULL) { try{ m_Counter = new int(1); } catch(std::bad_alloc &) { SAFE_DELETE(m_Pointer); throw; } } template <class T> inline CSmartPointer<T>::CSmartPointer(CSmartPointer<T> const &SmartPointer) : m_Pointer(SmartPointer.m_Pointer), m_Counter(SmartPointer.m_Counter) { ++(*m_Counter); } template <class T> inline CSmartPointer<T>::~CSmartPointer() { if( --(*m_Counter) == 0 ) { delete m_Pointer; delete m_Counter; } } template <class T> inline CSmartPointer<T> & CSmartPointer<T>::operator = (CSmartPointer<T> const &SmartPointer) { CSmartPointer<T> CopyTmp(SmartPointer); Swap(CopyTmp); return *this; } template <class T> inline CSmartPointer<T> & CSmartPointer<T>::operator = (T *Pointer) { CSmartPointer<T> CopyTmp(Pointer); Swap(CopyTmp); return *this; } template <class T> inline bool CSmartPointer<T>::operator () () { return(m_Pointer!=NULL); } template <class T> inline T const * const CSmartPointer<T>::operator -> () const { Assert( m_Pointer != NULL ); return m_Pointer; } template <class T> inline T * const CSmartPointer<T>::operator -> () { Assert( m_Pointer != NULL ); return m_Pointer; } template <class T> inline T const & CSmartPointer<T>::operator * () const { Assert( m_Pointer != NULL ); return (*m_Pointer); } template <class T> inline T & CSmartPointer<T>::operator * () { Assert( m_Pointer != NULL ); return (*m_Pointer); } template <class T> inline CSmartPointer<T>::operator T const * const() const { return m_Pointer; } template <class T> inline CSmartPointer<T>::operator T * const() { return m_Pointer; } template <class T> inline void CSmartPointer<T>::Swap(CSmartPointer<T> &SmartPointer) { std::swap(m_Pointer, SmartPointer.m_Pointer); std::swap(m_Counter, SmartPointer.m_Counter); } template <class T> template <class Other> inline CSmartPointer<T>::operator CSmartPointer<Other>() const { Other *Pointer = (Other *)m_Pointer; return CSmartPointer<Other>(Pointer); }Avec AddCamera prenant un smart pointer (de CCamera) en paramètre, dans ce cas il faut bien utiliser le constructeur en tant que conversion implicite non?
Code : Sélectionner tout - Visualiser dans une fenêtre à part SceneManager.AddCamera( new CCamera(*this) );
Enfin si vous avez d'autres conseils ou critiques sur le code je suis preneur encore merci à tous
NOTE : l'opérateur de conversion n'a pas encore était testé(), je ne suis pas sur que ce soit très correct (enfin j'y viendrai...)
Je pense que tu peux utiliser le swap aussi sur operator= (T*).
Et aussi, je te pose la question avant corrector: Constructeur implicite, c'est voulu ?
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
En effet ça semble fonctionner, c'est modifé merciEnvoyé par Médinoc
En prévision a cette question qui m'a était posé 3foisEt aussi, je te pose la question avant corrector: Constructeur implicite, c'est voulu ?j'ai laissé ce message :
Pourquoi cette question revient-elle? Il y a des risques (dans mon cas)?Envoyé par babar63
OK. En effet, là, le constructeur implicite est requis, je pense.
Et pour les risques, je ne sais pas trop à part des risques de confusion. J'ai surtout posé la question par mimétisme, parce que corrector la posait...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Dans la classe elle-même, tu peux écrire CSmartPointer à la place de CSmartPointer<T>.
Pourquoi faire un foncteur?
Pourquoi la distinction const/non const?
(Soit rigoureux dans ton explication.)Pourquoi faire une fonction séparée? Tu ne l'appelles qu'une seule fois.
Ces parenthèses sont redondantes.
Ces parenthèses sont redondantes.
Ces parenthèses sont redondantes.
Pourquoi SAFE_DELETE?
En effet, ce n'est pas forcément approprié. Mais ça peut aussi l'être, dépendant des circonstances. Enfin, je crois. Mais en y réfléchissant plus, je ne vois plus trop où, les exemples que j'avaient en tête s'écroulent dès que j'y pense plus d'une seconde...Pourquoi la distinction const/non const?
Pour bien faire, il faudrait peut-être deux versions de la classe: Une qui fait des contrôles comme ça, une autre où la constance de l'objet est complètement dissociée de celle du pointeur intelligent...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
D'après la FAQ c'est un prédicat si j'ai bien compris, je l'utilise simplement pour tester si mon objet pointé est valide(NULL) ou non.Envoyé par corrector
N'est-il pas correct d'utiliser un maximum de const lorsqu'on le peut? Voila un exemple de mon projet qui utilise la fonctionEnvoyé par corrector
Code : Sélectionner tout - Visualiser dans une fenêtre à part T const * const operator -> () const;Je suppose que je n'ai pas besoin de montrer d'exemple pour le même opérateur sans tous ces consts
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 //fonction membre de CSeneManager : std::vector<ILightPtr> const & GetLights() const { return m_Scene->Lights; // Un vecteur de ILightPtr membre de la class }, ce n'est donc pas correct? pourquoi?
Je fais de mon mieux mais je suis en train d'apprendre donc je ne peux pas toujours expliquer comme il le faudrait, sans doute je l'ai vu quelques part, ça m'a parut intelligent, j'ai gardé l'idée et je la ressort de temps en tempsEnvoyé par corrector
.
Justement je l'appelais dans mon opérateur :Envoyé par corrector
Que j'ai modifié à la suite de la remarque de médinoc, mais j'ai oublié de supprimer la fonction après...(je le fais de suite)
Code : Sélectionner tout - Visualiser dans une fenêtre à part CSmartPointer<T> & operator = (T *Pointer);Je préfère parfois mettre un peu plus de parenthèse, dans la limite du raisonnable je trouve le code plus clair... Est-ce un mauvais réflexe?Envoyé par corrector
Euh....Envoyé par corrector
.... Pour le coup j'avoue que je ne vois plus donc sans doute une mauvaise raison
. En revanche le deuxième :
est correct non? Je l'utilise pour supprimer m_Pointer si il est NULL et le réinitialiser à NULL
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 catch(std::bad_alloc &) { SAFE_DELETE(m_Pointer); throw; }
Le problème, c'est que ce code suppose que dès que le pointeur est constant, les données pointées le sont aussi.N'est-il pas correct d'utiliser un maximum de const lorsqu'on le peut? Voila un exemple de mon projet qui utilise la fonction
<snip>
Je suppose que je n'ai pas besoin de montrer d'exemple pour le même opérateur sans tous ces consts , ce n'est donc pas correct? pourquoi?
Si tu veux un smart pointer vers des données constantes, tu peux en faire un qui retourne toujours un T* et juste faire un CSmartPointer< const int > par exemple...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Partager