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 :

Pointeurs et constructeurs par copie


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Consultant E-Business
    Inscrit en
    Mai 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant E-Business

    Informations forums :
    Inscription : Mai 2007
    Messages : 39
    Par défaut Pointeurs et constructeurs par copie
    Bonjour à tous.

    Cela fait quelques temps que je n'ai pas fait de C++ digne de ce nom, j'ai donc quelques problèmes ...

    J'ai 2 classes : une classe Sommet et une classe Relation (pour des graphes).
    Ma classe relation possède en attributs privés 2 pointeurs sur Sommet (Sommet*) et un int pour le poids de la relation entre les sommets.
    Je veux construire tous ces objets dynamiquement afin de les contrôler entièrement.

    Le coeur du problème :

    Relation* r = new Relation(); // utilise le constructeur par défaut
    Relation* r2 = new Relation(r); // devrait utiliser le constructeur par copie

    constructeur par copie : Relation::Relation (const Relation&)

    En passant la relation r en paramètre, le compilo me dit qu'il est impossible de connvertir un 'Relation *' en 'const Relation'.

    Comment résoudre ce problème en laissant tout en dynamique ?

  2. #2
    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
    Quand tu fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Relation* r2 = new Relation(r);
    Ce que tu passe au constructeur de Relation c'est un pointeur et non un objet.

    Pour avoir un objet,il faut déférencer ton pointeur avec *.
    C'est à dire que ton instruction devient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Relation* r2 = new Relation(*r);
    "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)

  3. #3
    Membre averti
    Profil pro
    Consultant E-Business
    Inscrit en
    Mai 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant E-Business

    Informations forums :
    Inscription : Mai 2007
    Messages : 39
    Par défaut
    Plus d'erreur de compilation mais des violations mémoire...

    Voilà mon constructeur par copie :

    Relation::Relation (const Relation &r)
    {
    delete s1;
    delete s2;
    s1 = new Sommet(*r.s1);
    s2 = new Sommet(*r.s2);
    poids = r.poids;
    }

    Pour mes instances de Sommet, ça marche comme pour Relation.
    Sommet* s = new Sommet(5);
    Sommet* s2 = new Sommet(*s);

    Je pense donc que les étoiles dans les parenthèses de ces instructions sont utiles pour déréférencer le pointeur :
    s1 = new Sommet(*r.s1);
    s2 = new Sommet(*r.s2);

    Mais problème ...

  4. #4
    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
    s1 et s2 ne sont pas initialisés dans ton constructeur de copie, le delete (qui plus est inutile) a donc un comportement indéfini (et comme tu as du bol, c'est un plantage).
    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.

  5. #5
    Membre averti
    Profil pro
    Consultant E-Business
    Inscrit en
    Mai 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant E-Business

    Informations forums :
    Inscription : Mai 2007
    Messages : 39
    Par défaut
    Merci beaucoup !

    Le problème se situait donc au niveau des "delete toto" qui n'avait rien à faire là.
    J'ai une excuse, on m'avait dit de faire ça

    Donc pour ceux que ça intéresse :
    Objet* toto = new Objet(); ne nécessite pas de delete avant de refaire un new dessus

    Et lorsqu'on passe en paramètre un pointeur alors que la définition de la fonction/méthode a pour paramètre un <Objet &toto>, ne pas oublier de déréférencer le pointeur pour l'appel.

    Merci pour ces réponses très rapide, vraiment cool ce forum =))

  6. #6
    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
    Le delete sur une variable membre est typiquement à faire dans le destructeur, ou dans une fonction qui modifie.

    Mais clairement pas dans le constructeur sur un pointeur non-initialisé. Non seulement le delete sur un pointeur non-initialisé est un comportement indéfini (par opposition au delete NULL qui est garanti ne rien faire), mais ça n'a aucun sens: Puisque la variable n'existait pas avant, elle ne peux absolument pas pointer sur quelque chose.

    Pour une variable locale, il est important de faire le delete[] avant de "perdre" le dernier pointeur vers l'objet. Ne pas le faire est ce qu'on appelle une "fuite de mémoire".
    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.

+ 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