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


Sujet :

C++

  1. #1
    Candidat au Club
    Femme Profil pro
    Webmarketer
    Inscrit en
    Octobre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webmarketer

    Informations forums :
    Inscription : Octobre 2017
    Messages : 3
    Par défaut Constructeur de copie
    Bonjour à tous !

    Je suis néophyte sous C++, ainsi je suis confronté à un certains nombres de problème, probablement triviaux.
    Aujourd'hui, j'ai des problèmes pour concevoir un constructeur de copie.
    Voici mon code:
    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
     
    class arbre {
    public:
    	explicit
    	arbre( int valeur );
    	~arbre();
    	arbre(arbre & a);
    [Mes méthodes : hauteur(), new_gauche( arbre_binaire * nouveau_gauche );, gauche(), droite()...]
     
    private:
    	int valeur_;
    	arbre * gauche;
    	arbre * droite;
     
    arbre::arbre(arbre & a){
    	gauche_= a.gauche;
    	droit_ =a.droite;
    	valeur_= a.valeur;
    }
    Pour le constructeur de copie, je pensais faire très simplement le code ci-dessus, mais celui-ci ne marche pas. Je sens que je manque toute la profondeur de l'arbre avec celui-ci ? Et imagine donc un appel récursif du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    arbre_binaire::arbre_binaire(arbre_binaire & a){
    	gauche_= arbre_binaire( a.gauche_);
    	droit_ = arbre_binaire( a.droit_);
    	valeur_= a.valeur_;
    	++nombre_instances_;
    }
    Néanmoins cela ne compile pas, problème de type pointeur/ non-pointeur, mais je ne m'en sors pas trop.

    Si jamais vous pouvez m'aider, je vous remercie d'avance!

    Bonne journée,
    Giopi

  2. #2
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Voici une solution :
    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
    arbre::arbre(const arbre& a) :
    	valeur(a.valeur)
    {
    	if(a.gauche)
    		gauche = new arbre(*a.gauche);
    	else
    		gauche = nullptr;
     
    	try {    
    		if(a.droite)
    			droite = new arbre(*a.droite);
    		else
    			droite = nullptr;
     
    	} catch(...) {
    		delete gauche;
    		throw;
    	}
    }
    Cela dit, pour éviter d'alourdir le code avec des try-catch, il est généralement déconseillé de manipuler la mémoire dynamique avec des pointeurs nus.
    Si gauche et droite sont de type std::unique_ptr<arbre>, le code devient bien plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    arbre::arbre(const arbre& a) :
    	valeur(a.valeur)
    {
    	if(a.gauche)
    		gauche = std::make_unique<arbre>(*a.gauche);
    	if(a.droite)
    		droite = std::make_unique<arbre>(*a.droite);
    }

  3. #3
    Candidat au Club
    Femme Profil pro
    Webmarketer
    Inscrit en
    Octobre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webmarketer

    Informations forums :
    Inscription : Octobre 2017
    Messages : 3
    Par défaut
    Merci beaucoup pour votre aide !
    Petit point de détails : est-ce qu'il est conseillé de manipuler exclusivement des pointeurs intelligents, que ce soit unique_ptr ou shared_ptr, ou bien d'utiliser des pointeurs nus ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    pyramidev a donné deux manières de gérer les pointeurs. Aurais-tu trouvé la première? Si non, il est fortement conseillé d'utiliser les pointeurs intelligents. Essaie maintenant d'écrire l'opérateur de copie dans ces deux cas, d'autant qu'en utilisant les pointeurs bruts il faut impérativement le définir (et tu sembles l'avoir oublié) alors qu'avec les pointeurs intelligents il n'y a pas de risque de bug si on l'oublie.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    arbre &arbre::operator=( const arbre& a ) ...

  5. #5
    Candidat au Club
    Femme Profil pro
    Webmarketer
    Inscrit en
    Octobre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webmarketer

    Informations forums :
    Inscription : Octobre 2017
    Messages : 3
    Par défaut
    Pour l'opérateur de copie, j'avais suivi les conseils que j'ai reçu par ailleurs, en utilisant la bibliothèque standard, dans le but d'éviter des erreurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    arbre & arbre::operator = ( arbre& a){
    	swap(a);
    	return *this;
    }
     
    void arbre::swap(arbre& a){
    	using std::swap;
    	swap(valeur, a.valeur);
    	swap(gauche, a.gauche);
    	swap(droite, a.droite);
     
    }
    Je n'aurais pas su gérer les erreur avec le try, catch, throw assurément dans la première réponse apportée !

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    En l'état ton code est plus proche d'un déplacement que d'une copie. Les objets sont swap, autant l'objet destination aura bien les valeurs de l'objet source, autant l'objet source est dans un état bien batard puisqu'il se retrouve avec les valeurs de l'objet destination.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    La fonction swap() est nickel.
    Cette manière d'écrire l'opérateur de copie est intéressante (et elle fonctionne aussi bien avec des pointeurs bruts que des pointeurs intelligents), mais il y a une petite erreur qui fait qu'il modifie la source alors qu'il ne devrait que la copier.
    En utilisant le bon prototype avec le qualificateur const arbre& arbre::operator=( const arbre& a );, le compilateur t'aurait prévenu qu'il y a erreur. On peut aussi utiliser le prototype arbre& arbre::operator=( arbre a );

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Dans le cas où l'objet est un peu lourd, faire une copie pour faire un swap ne me semble pas une bonne idée.
    Mais sinon oui, c'est un trick intéressant. A garder dans sa poche, comprendre et maitriser pour l'utiliser au moment opportun.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par giopi Voir le message
    Petit point de détails : est-ce qu'il est conseillé de manipuler exclusivement des pointeurs intelligents, que ce soit unique_ptr ou shared_ptr, ou bien d'utiliser des pointeurs nus ?
    Non. Tu ne dois prendre des pointeurs des intelligents que lorsque la gestion de la durée de vie du pointeur est gérée par "quelqu'un d'autre", et que tu es certain que ton pointeur nu ne survit jamais à l'objet alloué qui lui est associé.

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Tu ne dois prendre des pointeurs des intelligents que lorsque la gestion de la durée de vie du pointeur est gérée par "quelqu'un d'autre"
    Pourquoi cette restriction?
    Qu'est-ce qu'il y a de mal avec ce code?
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int SomeFunction()
    {
    	auto_ptr<SomeType> spObj = make_unique<SomeType>();
    	return spObj->SomeOperation();
    }
    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.

  11. #11
    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
    Salut,
    Citation Envoyé par oodini Voir le message
    Non. Tu ne dois prendre des pointeurs des intelligents que lorsque la gestion de la durée de vie du pointeur est gérée par "quelqu'un d'autre", et que tu es certain que ton pointeur nu ne survit jamais à l'objet alloué qui lui est associé.
    Excuses moi, mais là, j'ai envie de m'écrirer "c'est quoi cette connerie"

    Tu dois toujours avoir recours au pointeurs intelligents!!!

    A toi de déterminer qui sera le propriétaire légitime de la ressource!

    C'est l'utilisation des pointeurs bruts qui doit être strictement encadrée et dont on peut éventuellement envisager que celui qui disposera d'un tel pointeur ne pourra faire qu'utiliser la ressource, sans aucun droit de la libérer, et, bien sur, après s'être assurer que le propriétaire légitime de la ressource ne décidera pas de la libérer alors qu'on est occupés avec.
    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

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par koala01 Voir le message
    C'est l'utilisation des pointeurs bruts qui doit être strictement encadrée et dont on peut éventuellement envisager que celui qui disposera d'un tel pointeur ne pourra faire qu'utiliser la ressource, sans aucun droit de la libérer, et, bien sur, après s'être assurer que le propriétaire légitime de la ressource ne décidera pas de la libérer alors qu'on est occupés avec.
    C'est exactement ce que j'ai dit.

    Mea culpa : Ma pensée a bifurqué en cours de rédaction de mon message tant critiqué. J'ai commencé la phrase en partant sur l'utilisation des pointeurs intelligents, pour la terminer en parlant du cas d'utilisation des pointeurs bruts... On peut d'ailleurs voir qu'une syntaxe très hasardeuse matérialise ce "switch".
    Je vais mettre ça sur l'heure de la rédaction dudit message...

  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
    Ah, méa culpa, mea maxima culpa. Toutes mes excuses, alros, car je n'avais vraiment pas compris ton message en ce sens
    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
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Pourquoi cette restriction?
    Qu'est-ce qu'il y a de mal avec ce code?
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int SomeFunction()
    {
    	auto_ptr<SomeType> spObj = make_unique<SomeType>();
    	return spObj->SomeOperation();
    }
    J'imagine que cet ignoble auto_ptr est juste une faute de frappe, et que tu voulais juste écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    unique_ptr<SomeType> spObj = make_unique<SomeType>();
    // Ou
    auto spObj = make_unique<SomeType>();
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Oui, c'est une faute de frappe. C'est bien unique_ptr des deux côtés.
    Ou probablement juste auto. J'ai dû faire l'amalgame des deux.
    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.

  16. #16
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Pourquoi cette restriction?
    Qu'est-ce qu'il y a de mal avec ce code?
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int SomeFunction()
    {
    	auto_ptr<SomeType> spObj = make_unique<SomeType>();
    	return spObj->SomeOperation();
    }
    Hum...

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int SomeFunction()
    {
    	SomeType spObj;
    	return spObj.SomeOperation();
    }

    Certes, on peut utiliser des pointeurs intelligents localement, c'est très bien, mais régulièrement, ce n'est pas du tout nécessaire.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

Discussions similaires

  1. [résolu]les constructeurs de copie
    Par pouss dans le forum Langage
    Réponses: 9
    Dernier message: 28/06/2005, 10h57
  2. Réponses: 3
    Dernier message: 24/04/2005, 14h19
  3. [C++]Heritage et constructeur de copie
    Par matazz dans le forum C++
    Réponses: 2
    Dernier message: 25/03/2005, 12h31
  4. Constructeur de copie modifiant le paramètre ?
    Par Nicodemus dans le forum C++
    Réponses: 4
    Dernier message: 12/01/2005, 21h25
  5. 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