IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Constructeurs par copie : laisser le compilo gérer ?


Sujet :

Langage C++

  1. #1
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut Constructeurs par copie : laisser le compilo gérer ?
    Bonjour à tous,

    Après relecture de Effective C++ (histoire de passer le temps dans le train), Scott Meyers mets le doigt sur un point assez délicat : le constructeur par copie généré par le compilo effectue une copie de tous les membres de la classe. Donc en cas d'évolution ultérieure, il n'y a pas besoin de modifier quoique ce soit, le compilo se chargera des membres supplémentaires. Alors que nous, humbles programmeurs, on pourrait oublier de le modifier, ce constructeurs par copie !
    J'avoue que cette "facilité" est assez sympathique, et m'amène donc aux questions suivantes :
    1. Peut-on laisser le compilo générer le constructeur par copie et ne s'occuper que de l'opérateur d'affectation (avec copy and swap ) ?
    2. Dans quels cas il faut absolument le faire à la main ?



    Typiquement, pour ce genre de code, j'aurai envie de laisser le compilo gérer. A part certains cas particuliers (variables non copiables genre mutex, etc.), je pense pas que ça pose problème!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Widget
    {
    public:
        virtual void Draw() const = 0;
        // Other functions
     
    private:
        boost::shared_ptr<Shape> m_shape_ptr;
        int m_id;
        std::vector<std::string>    m_elements_name;
    };
    Vous en pensez quoi ?

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Points : 1 174
    Points
    1 174
    Par défaut
    ben oui il faut que tu fasses du code seulement si tu as besoin d'un comportement particulier.

    Si une classe attribut n'est pas copiable, la tienne en sera pas copiable non plus.

    Enfin l'intérêt du C++ quand même c'est qu'il y a beaucoup de choses qu'on est pas obligé de faire ( si on l'utilise de manière basique sans pointeur etc.. )

  3. #3
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Bonjour,
    Je pense qu'on devrai toujours se demander si un objet a vraiment besoin d'être copiable. Par exemple widget est un objet polymorphique, il ne faudrait donc mieux pas qu'il soit copiable. En tout cas pas en public. Pour éviter le slicing.

    Après, pour les objets qui doivent vraiment être copiable, ben si le constructeur par copie est suffisant alors pourquoi s'embêter? Il faut surtout faire attention aux pointeurs. Doit-on copier le pointeur? ou allouer un nouvel objet? Typiquement, avec un shared_ptr, les deux options sont possible. Si tu veux allouer un nouvel objet, il faudra définir un constructeur par copie.

  4. #4
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Citation Envoyé par nikko34 Voir le message
    ben oui il faut que tu fasses du code seulement si tu as besoin d'un comportement particulier.
    Enfin l'intérêt du C++ quand même c'est qu'il y a beaucoup de choses qu'on est pas obligé de faire ( si on l'utilise de manière basique sans pointeur etc.. )
    Oui c'est sûr. J'avais juste pas mal entendu sur le forum qu'il vallait mieux définir le trio constructeur / copie / affectation pour une classe "complexe". Bon, j'avais peut-être pas tout compris non plus.

    Citation Envoyé par Nogane Voir le message
    Bonjour,
    Je pense qu'on devrai toujours se demander si un objet a vraiment besoin d'être copiable. Par exemple widget est un objet polymorphique, il ne faudrait donc mieux pas qu'il soit copiable. En tout cas pas en public. Pour éviter le slicing.
    Là, Widget n'était qu'un exemple. Dans une hierarchie polymorphe, on aurait intérêt à passer par Clone() pour renvoyer un type dérivé. Sauf si on gère tout par shared_ptr (comme moi) où on est obligé de renvoyer un type de base...
    Le problème de slicing, c'est à la charge du "client". S'il passe par copie au lieu de passer par référence constante, c'est bien dommage...

    Citation Envoyé par Nogane
    Après, pour les objets qui doivent vraiment être copiable, ben si le constructeur par copie est suffisant alors pourquoi s'embêter? Il faut surtout faire attention aux pointeurs. Doit-on copier le pointeur? ou allouer un nouvel objet? Typiquement, avec un shared_ptr, les deux options sont possible. Si tu veux allouer un nouvel objet, il faudra définir un constructeur par copie.
    On est d'accord., le compilo le fait très bien pour nous dans 99 % des cas. Car on attend le plus souvent shared_ptr qu'il partage la nouvelle donnée...

    à vous deux !!

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    En fait, la règle est plutôt: si tu définis un constructeur non trivial (par exemple, parce qu'il fait une allocation dynamique de la mémoire), tu devrais redéfinir le constructeur par copie, l'opérateur d'affectation et le destructeur.

    Le tout, modulo les besoins et limitations de ta classe: si ta classe est sensée ne pas être assignable et /ou copiable, tu déclares l'opérateur d'affectation et / ou le constructeur par copie en accessibilité privée, sans les définir (ou tu les déclare delete en C++0x)

  7. #7
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 861
    Points
    11 861
    Par défaut
    Il y a une catégorie de situations où tu DOIS considérer un constructeur de copie fait maison, ou au moins te poser la question : quand tu as en attribut un pointeur.

    La question c'est est-ce que tu veux que la copie de ton objet détienne la même adresse (le pointeur lui-même, quoi) ou alors la même instance (ce qui est pointé par le pointeur). Si c'est le premier, pas besoin de faire ton constructeur par copie, mais en gardant à l'esprit que quand l'objet que l'on a copié risque de faire un delete du pointeur dans son destructeur et que ça invaliderait donc le pointeur de ta copie. Si c'est le deuxième, là tu dois considérer le constructeur par copie fait maison. Mais tout ça est bien résumé dans la FAQ.

  8. #8
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    En effet !
    La FAQ reste assez "haut niveau" dessus (en parlant de sémantique), alors que je cherchais des cas concrets en rapport à l'item 5 de Effective C++ de Scott Meyers.
    Au final, tout se passe comme je pensais.

    Merci à tous.

  9. #9
    screetch
    Invité(e)
    Par défaut
    Je dirai que pour les classes qui contiennent plusieurs champs, pour les rendre copiables je prefere que chaque champ soit copiable individuellement. Si il y a un champ non copiable (un handle, un pointeur) je préfère l'encapsuler dans une classe comme un smart pointeur ou un truc similaire, et ainsi laisser le constructeur de copie original.
    Mais ca c'est plus la theorie, je suis sur qu'en pratique je le fais pas souvent...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [POO] Constructeur par copie
    Par kacedda dans le forum C++
    Réponses: 16
    Dernier message: 05/05/2007, 12h38
  2. [Debutant] Problème avec un constructeur par copie
    Par Drannor dans le forum Débuter
    Réponses: 5
    Dernier message: 12/03/2007, 09h15
  3. Réponses: 5
    Dernier message: 03/12/2006, 15h55
  4. Constructeur par copie et std::list
    Par Captain_JS dans le forum SL & STL
    Réponses: 5
    Dernier message: 13/12/2005, 19h15
  5. [deb.]Constructeur par copie
    Par Marc_3 dans le forum Débuter
    Réponses: 4
    Dernier message: 19/11/2005, 13h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo