[C++] Affectation par dtor+ctor de copie ?

Affectation par dtor+ctor de copie ? [C++] - Programmation

Marsh Posté le 03-06-2002 à 12:50:46    

J'aime bien définir l'opérateur d'affectation comme suit:

Code :
  1. Class Truc {
  2.   //...
  3.   Truc& operator=(const Truc & rh){
  4.     if(this != &rh){
  5.       this->Truc::~Truc() ; //détruire l'ancienne valeur
  6.       this->Truc::Truc(rh) ; //copier la nouvelle valeur avec le constructeur de copie
  7.     }
  8.     return *this ;
  9.   }
  10. }


Le concept me semble valable, ça marche, mais...
D'une part, Bjarne Stroustrup écrit qu'il faut éviter d'appeler directement les constructeurs/destructeurs si ce n'est pas indispensable.
D'autre part, je me demande si les constructeurs/destructeurs font un travail supplémentaire invisible. Par exemple, pour permettre à "throw" de détruire corectement les objets dont il ne connaît rien.
 
Qu'en pensez-vous ?


Message édité par Musaran le 06-03-2002 à 12:53:28

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 03-06-2002 à 12:50:46   

Reply

Marsh Posté le 03-06-2002 à 13:06:06    

C pas térible en effet, mieux vaut faire une méthode de recopie qui va te recopier les données de l'objet source dans l'objet courrant et l'appeler dans l'oppérateur d'affectation et dans le constructeur de recopie, c'est plus propre et d'un résultat moin hazardeux.


---------------
Le Tyran
Reply

Marsh Posté le 03-06-2002 à 20:46:31    

En quoi serait-ce hasardeux ?
 
Dans l'affectation, il faut bien libérer les anciennes ressources pour copier les nouvelles, et c'est exactement ce que font le destructeur et le constructeur de copie.
 
Il n'y a même pas besoin de mettre ce code à jour si on change la structure de la classe.
 
Je dirait presque que ceci aurait dû être l'opérateur d'affectation par défaut !
Mais je ne m'y connaît pas suffisamment pour voir d'éventuels problèmes...


Message édité par Musaran le 06-03-2002 à 20:46:46

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 03-06-2002 à 20:56:09    

Par ce qu'il est clairement dit qu'on ne doit pas appeler directement les constructeurs et destructeur, la chose n'étant pas prévu dans la norme tu ne peux absolument pas prévoir le comportement des compilateurs
En plus tu détruit un objet et après tu appel une méthode de cette objet ce qui est totalement abhérant (et ne passe pas avec certains compilos à mon avis)


Message édité par LetoII le 06-03-2002 à 21:01:52

---------------
Le Tyran
Reply

Marsh Posté le 04-06-2002 à 10:24:35    

Dans son livre de référence du C++, Bjarne Stroustrup mentionne cette possibilité, et se contente de recommander de ne pas le faire s'il y a un autre moyen.
 
La "méthode" spéciale constructeur n'a, par définition, pas besoin d'un objet valide, puisque c'est justement elle qui est chargée de les rendre ainsi.
 
Et puis de toutes façon, quand quelque chose est interdit, je dois savoir pourquoi, sinon j'en tiens pas compte :lol: .


Message édité par Musaran le 06-04-2002 à 10:24:56

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 04-06-2002 à 13:07:25    

Faudra pas t'étonner si t'as des problèmes dans tes progs


---------------
Le Tyran
Reply

Marsh Posté le 04-06-2002 à 13:21:52    

on peut aussi utiliser un new de placement :
new (this) Truc(param);
this est utilisé ici seulemnt comme un void* qui pointe vers un buffer de taille sizeof(Truc).
 
ça me semble a priori plus propre que ton truc.
 
 
 
 
ça me fait penser à un bout de code dégueulasse que j'ai vu une fois :
 
class Toto
{
public:
    static void f(void);
};
 
puis:
 
Toto * t = 0;
t->f();
 
ça marche à la compil et à l'exec, mais c'est inutile et dangereux

Reply

Marsh Posté le 04-06-2002 à 13:34:23    

L'appel au destructeur explicite est
valide tant que tu respectes certaines regles.
 
Cas classique d'appel au destructeur explicite apres un placement new:

Code :
  1. char memory[sizeof(MonObjet)];
  2. void* p = memory;
  3. MonObjet* m = new(p) MonObjet();
  4. // ...
  5. m->~MonObjet();


 
A noter, que l'appel au destructeur explicite est la seule facon de detruire un objet construit par placement new.
 
Par contre:  

Code :
  1. MonObjet toto*;
  2. /*..*/
  3. toto->~MonObjet();
  4. toto->MonObjet(nouvelle valeur); // c'est totalement stupide


 
Pourquoi est-ce stupide d'appeler le constructeur MonObjet() sur toto? tout simplement parce que tu ne sais pas de quel type est l'objet pointé par toto. Il peut etre 'MonObjet' comme il peut etre une classe fille.  
 
LeGreg


Message édité par LeGreg le 06-04-2002 à 13:39:51
Reply

Marsh Posté le 04-06-2002 à 18:14:49    

letoII a écrit a écrit :

Faudra pas t'étonner si t'as des problèmes dans tes progs



Si c'est dangereux, illégitime ou bogué, je veux savoir pourquoi, c'est important pour moi.
 
Simplement dire "faut pas" ne me satisfait pas.
 

pulco-citron a écrit a écrit :

on peut aussi utiliser un new de placement


Le new, de placement ou pas, implique un appel a delete.
On ne peut pas demander à l'utilisateur de Truc d'y penser !
 
Quand à ton exemple "t->f()", il est effectivement dangereux, car il ne marchera pas si f n'est plus statique, et que le codeur risque de croire qu'il a un objet pointé.
 
C'est "Toto::f()" qu'il aurait fallu écrire.
Et pourtant... si on change le type pointé par t, ça ne suit pas le changement, et pire encore sans message d'erreur !
C'est pourquoi on peut préférer écrire "t->f()", qui est une méthode d'appel légitime pour une fonction de classe statique.
 

legreg a écrit a écrit :

L'appel au destructeur explicite est valide tant que tu respectes certaines regles.


Lesquelles ?
 
Ton exemple d'appel explicite au constructeur est effectivement à manier avec précaution.
Si le destructeur de la classe est virtuel, que se passe t'il ? On détruit un objet dérivé pour contruire un objet de base ?


Message édité par Musaran le 06-04-2002 à 18:16:41

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 04-06-2002 à 18:32:24    

Quand ces bien fait les destructeur d'une chaîne de dérivation sont virtuels ça ne pose normalement pas de problème de scôté là, le bon destructeur est appelée. Encore faut il que ça ai été bien fait au départ.


---------------
Le Tyran
Reply

Marsh Posté le 04-06-2002 à 18:32:24   

Reply

Marsh Posté le 04-06-2002 à 18:34:12    

Et puis au passage je trouve tout ça assez crade, mais bon c juste un avis personnel :D


---------------
Le Tyran
Reply

Marsh Posté le 04-06-2002 à 18:38:51    

Citation :

Lesquelles ?


 
Ben je t'ai donné la seule ou tu es obligé de le faire..
Tu peux appeler un destructeur plusieurs fois si tu t'assures
qu'il est reentrant.
 

Citation :

Ton exemple d'appel explicite au constructeur est effectivement à manier avec précaution.


 
Tu n'as pas compris: il n'est pas a manier avec precaution, il est a OUBLIER. Ne jamais coder comme ca, ce code est invalide en C++.
 

Citation :

Si le destructeur de la classe est virtuel, que se passe t'il ? On détruit un objet dérivé pour contruire un objet de base ?


 
Si le destructeur est virtuel on appelle destructeur de la classe fille. (pour un destructeur, "virtuel" ca a le meme sens que pour n'importe quelle fonction).
Et on ne construit pas un objet de base derriere puisque le code que j'ai ecrit est invalide. On ne l'ecrit jamais. (demande toi pourquoi il n'y a pas de constructeur virtuel en C++).
 
Pour faire ce que tu veux, passe par une fonction assign() et destroy() séparées que tu appelles depuis le constructeur et le destructeur. Ces fonctions seront eventuellement virtuelles suivant ce que tu veux faire.
 
A+
LeGreg

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed