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

 C++ Discussion :

Constructeur de copie, et opérateur d'affectation.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Constructeur de copie, et opérateur d'affectation.
    Bonjour à tous,

    Pour les classes à sémantique de valeur, on définie très souvent, un constructeur de copie ou un opérateur d'affectation= . J'aimerais savoir quelles sont les différences entre ces deux méthodes particulière. Est-ce qu'elles jouent eux deux le même rôle ? Et dans quel cas et but les utilise-t-on ?

    Merci à ceux qui apporteront des réponses à mes questions.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MaClasse(const &MaClasse);
    MaClasse& operator=(const &MaClasse);

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    Bonsoir,

    copie et affectation ne sont pas la même chose
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class C { ... };
    C c1; // constructeur
    C c2(c1); // constructeur par copie
     
    c2 = c1; // affectation
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Comme son nom l'indique, le constructeur par copie construit un nouvel objet, alors que l'opérateur d'affectation opère sur un objet existant.

    Par exemple, un quiz classique : Qu'affiche chacune des lignes suivantes ?
    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
     
    #include <iostream>
    struct MaClasse
    {
       MaClasse(){std::cout << "Default Ctor\n"; }
       MaClasse(const MaClasse&){std::cout << "Copy Ctor\n"; }
       MaClasse& operator=(const MaClasse&){std::cout << "Op = \n"; return *this;}
    };
     
    int main()
    {
       MaClasse m1;
     
       MaClasse m2(m1);
       MaClasse m3 = m2;
       MaClasse m4 = MaClasse();
     
       m1 = m2;
    }

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    vu ma réponse précédente cela ne devrait pas être trop difficile
    (je suppose qu'on a commencer à répondre en même temps et que j'ai fini avant, mais comme on ne peut pas prendre de mutex pour rendre les réponses exclusives ... )
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Bien qu'ils soient appelé à des moments différents, ils font la même chose (il n'y qu'a voir l'idiom copy & swap). Donc si tu dois en définir un, tu dois aussi en définir l'autre.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Pensez à privilégier l'affectation par copy and swap pour les objets contenants des ressources à copier. ca a aussi l'avantage d'eviter la duplication de code entre C(C const&) et operator=(C const&)

  7. #7
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    J'vais quand même corriger mon p'tit code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    C & operator=(C v)
    {
     swap(v.members,this->members);
     return *this;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    C & operator=(C const & v)
    {
     C tmp(v);
     swap(tmp.members,this->members);
     return *this;
    }
    J'espère que c'est plus mieux comme ça (il fait tard à c't'heure, il fait fatigué...)

    Mais c'est quand même la première fois que je vois le copy&swap remit en cause. Il est pourtant prouvé que c'est la cata de ne pas l'utiliser en cas de références cycliques.

    EDIT: et m.... j'ai édité au lieu d'ajouter un post... allez dodo...

  8. #8
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    bigre diantre, quand j'écris a=b je ne veux surtout pas modifier b !

    ce qui est curieux c'est donc d'utiliser swap, qu'elle idée aussi sotte que grenue
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  9. #9
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Bah, tu crées la copie (RAII etc) au passage. Mais là où tu gagnes c'est dans par exemple ce genre de cas :

    C makeC();
    C c;
    c = makeC();

    Ici comme le paramètre bind à une rvalue, la copie est (tout le temps?) passée à la trappe.

    @Bruno_pages : sisi ... le copy and swap est LA bonne façon de faire. Et rien n'est modifié hein. (pour ça qu'on crée une copie temporaire).

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bah ça alors, je vois que c'est partit en délire total... Plus sérieusement, j'ai commencé à lire, mais je me suis vite fait largué. Je répond au premier post :
    Citation Envoyé par Arzar Voir le message
    Comme son nom l'indique, le constructeur par copie construit un nouvel objet, alors que l'opérateur d'affectation opère sur un objet existant.

    Par exemple, un quiz classique : Qu'affiche chacune des lignes suivantes ?
    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
     
    #include <iostream>
    struct MaClasse
    {
       MaClasse(){std::cout << "Default Ctor\n"; }
       MaClasse(const MaClasse&){std::cout << "Copy Ctor\n"; }
       MaClasse& operator=(const MaClasse&){std::cout << "Op = \n"; return *this;}
    };
     
    int main()
    {
       MaClasse m1;//Affiche : Default Ctor
     
       MaClasse m2(m1);//Affiche : Copy Ctor
       MaClasse m3 = m2;//Affiche : Op = 
       MaClasse m4 = MaClasse();//Affiche : Default Ctor
     
       m1 = m2;//Affiche : Op = 
    //J'ai pas testé, mais je pense que c'est ça...
    }
    Voilà, j'ai pas tester, mais je pense que c'est ça. Ensuite, certains parle de copy&swap, c'est quoi au juste ?

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Abdelite Voir le message
    Voilà, j'ai pas tester, mais je pense que c'est ça. Ensuite, certains parle de copy&swap, c'est quoi au juste ?
    C'est un idiome permettant d'implementer l'operateur d'assignation en utilisant une fonction realisant un swap (cette fonction doit avoir ete implementee a part, il ne faut pas utiliser std::swap qui utilise l'assignation ).

    L'assignation se resume alors a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Foo& operator=(Foo f)
    {
       swap(*this, f);
       return *this;
    }
    (La copie est dans le fait qu'on passe par valeur -- faire ainsi a l'avantage que le compilateur peut parfois elider une copie quand on assigne un temporaire -- le resultat d'une fonction par exemple).

    Cet idiome a l'avantage d'etre une maniere systematique d'ecriture un operateur d'assignation robuste en cas d'exception pour autant qu'on dispose d'un swap (voir ma note sur std::swap) n'en jetant pas (si on n'est pas capable d'ecrire un swap qui ne jette pas d'exception, ecrire une assignation robuste ne va pas etre simple et on peut se demander l'interet de fournir ces operations a la classe) -- soit l'operation reussit, soit l'objet que l'on cherche a modifie ne l'a pas ete.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    C'est un idiome permettant d'implementer l'operateur d'assignation en utilisant une fonction realisant un swap (cette fonction doit avoir ete implementee a part, il ne faut pas utiliser std::swap qui utilise l'assignation ).
    Un idiome ?
    Un swap, c'est bien un échange de valeurs entre deux classes n'est-ce pas ?

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    (La copie est dans le fait qu'on passe par valeur -- faire ainsi a l'avantage que le compilateur peut parfois elider une copie quand on assigne un temporaire -- le resultat d'une fonction par exemple).
    Je n'ai pas très bien compris... Tu entends quoi par élider ?

    Vraiment désolé, je sais que j'ai un niveau très déplorable en C++, mais je ne demande qu'à m'améliorer. Essayer d'utiliser des termes très basique pour que je comprenne bien, merci à vous

  13. #13
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Un idiome pourrait être considéré comme "une manière de faire" propre à un langage donné, permettant d'assurer à la fois une implémentation "simple" (parce que répétée sans arrêt) et sécurisante (parce que, justement, on l'implémente souvent, et que, en plus, il est possible de prendre une série de problème en compte qu'il serait difficile de cumuler si on n'utilisait pas l'idiôme).
    Un swap, c'est bien un échange de valeurs entre deux classes n'est-ce pas ?
    C'est bien cela...

    Élider: éviter, supprimer ce qui est "inutile"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Abdelite Voir le message
    Un idiome ?
    En simple, une recette de cuisine. Une façon de faire quelque chose.

    Un swap, c'est bien un échange de valeurs entre deux classes n'est-ce pas ?
    oui

    Tu entends quoi par élider ?
    éviter.
    En gros le compilateur va optimiser en enlevant des copie inutile du code.

    Citation Envoyé par Abdelite Voir le message
    Vraiment désolé, je sais que j'ai un niveau très déplorable en C++, mais je ne demande qu'à m'améliorer.
    Aucun problème

  15. #15
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Abdelite Voir le message
    Voilà, j'ai pas tester, mais je pense que c'est ça.
    Tu devrais peut être faire le test tout de même, tu pourrais avoir des surprises :
    • MaClasse m3 = m2 appelle le constructeur par copie.
    • Suivant le compilateur et les options de compilations, MaClasse m4 = MaClasse() appelle soit le constructeur par défaut soit le constructeur par défaut puis le constructeur par copie.

  16. #16
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Voila un code d'exemple sur les elisions et les copies de rvalue que Dave avait foruni dans les commentaires sur c++-next.com

    http://codepad.org/aG4BBT8g

  17. #17
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Joel F Voir le message
    Voila un code d'exemple sur les elisions et les copies de rvalue que Dave avait foruni dans les commentaires sur c++-next.com

    http://codepad.org/aG4BBT8g
    C'est quel compilateur qui manque tout? (Ici, gcc et xlC ne manquent qu'une élision au dernier -- si en théorie elle est possible, en pratique il faudrait que le compilo fasse l'élision après avoir inliné pour y arriver -- et SunCC manque le nrvo en plus).

Discussions similaires

  1. Réponses: 1
    Dernier message: 03/02/2015, 15h21
  2. Réponses: 7
    Dernier message: 17/08/2014, 15h20
  3. Réponses: 96
    Dernier message: 08/04/2013, 11h54
  4. Constructeur de copie et Template: Transtypage
    Par ikkyu_os dans le forum Langage
    Réponses: 9
    Dernier message: 26/12/2004, 22h29

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