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 :

desallocation de Pointeurs passés en variables


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 31
    Par défaut desallocation de Pointeurs passés en variables
    Bonjour à tous,
    Je vous écris car j’ai une question concernant les pointeurs. Avant de vous poser la question je vous explique mon architecture histoire de comprendre à peu près ce que je fais. J’espère ne pas être trop long mais bon .
    Donc dans mon architecture, j’ai 3 classes. Appelons ces classes CFenetre, CAlgo et CElement. Tout commence dans la classe CFenetre car je modifie (gère) les attributs de CElement avec mon interface. Une fois les attributs mise a jour, je fais appel a la classe CAlgo pour faire ce que j’ai besoin, a savoir que j’utilise la classe CElement dans CAlgo aussi.
    En gros, dans CFenetre, je crée un pointeur CElement et je l’alloue. Apres l’allocation je lie le pointeur dans la classe CAlgo, soit un code du genre pour CFenetre :

    Dans le header :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CElement *Element ;
    CAlgo *Algo ;
    Dans le constructeur de la classe CFenetre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Element = new CElement(Variables) ;
    Algo = new CAlgo (Variables) ;
    Algo->LinkClass(Element)
    Dans le destructeur de la classe CFenetre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    delete Element ; 
    delete Algo ;
    //n'oublions pas les deletes :)
    En cliquant sur des boutons de mon interface, je fais appel à des fonctions de ma classe CAlgo, et le lien dans la classe CAlgo pour CElement se fait avec LinkClass de la sorte suivante :

    Dans le header de CAlgo:
    Dans les sources:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void CAlgo::LinkClass(CElement *Elem)
    {
    	ElementA = Elem ;
    }
    Ma question est la suivante : Avec cette façon de faire, dans le destructeur de CAlgo, dois-je aussi faire un delete de ElementA ?

    En espérant avoir été assez clair, merci de votre temps.
    Eagl.

  2. #2
    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
    L'utilisation de pointeurs est-elle indispensable ?
    Car ce n'est pas apparent, ici.

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 31
    Par défaut
    Salut, merci de ta manifestation,
    Au début je n’utilisais pas de pointeur, et en changeant les valeurs des attributs avec l’interface durant une animation (j’affiche les résultats en temps réel), les nouvelles valeurs des variables n’étaient pas prises en compte. Donc j’ai pensé à utiliser des pointeurs et sans même changer le code, juste en changeant le type de variable, badaboume, ca marche. Donc il y a peut être une solution sans pointeur mais ca m’a paru plus simple comme ca sur le moment.
    L’avantage est aussi que je n’ai pas besoin de mettre à jour ElementA dans CAlgo à chaque fois que je change les valeurs de Element dans CFenetre, tout est implicitement direct avec des pointeurs.
    Ceci dit, si c’est très mauvais de faire comme, dites le moi (dites le pourquoi aussi si c’est possible), et j’essaierai de trouver une alternative.
    Mais donc, en faisant comme ca, faut-il un delete dans CAlgo pour ElementA ? Je sais que dans le pire des cas, je peux mettre ce delete. Car même si ElementA n’existe plus au moment du delete, aucune erreur ne se produira. Le delete sera tout simplement ignorer si il n’est pas utile. Je pose la question vraiment par curiosité pour des soucis de meilleur compréhension.

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 264
    Par défaut
    Salut,

    Permets-moi de rectifier ton titre, on ne désalloue pas les pointeurs, mais la mémoire vers laquelle ils pointent.
    C'est très important pour comprendre que dans ton cas, le delete Elem a déjà libéré la mémoire qui est encore pointée par ElementA. Dès lors, si tu tentes d'utiliser celle-ci depuis ElementA, tu t'exposes à des problèmes (bugs aléatoires, plantages)...

    Donc, pour répondre à ta question, tu ne dois surtout pas appeler delete ElementA, et tu ne dois plus manipuler l'objet pointé par ElementA après que delete Elem a été appelé.

    Je te conseille de bien formaliser sur le papier les responsabilités entre tes objets et de définir clairement qui est le propriétaire de ton élément. Le propriétaire seulement aura alors la charge de l'allocation et de la désallocation de l'élément. A priori, ici ça serait ta classe CFenetre, puisque ce sont tes instances de CFenetre qui possèdent des CElements et il y a fort à parier qu'ici, le propriétaire de Algo soit le même objet.

  5. #5
    Membre averti
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 31
    Par défaut
    Salut Niark13,
    Pour le titre je me disais bien que ce n’était pas très juste pour les expressions utilisées, je ne savais pas quoi exactement mettre. (Tu conseilles ?)
    Je vois que tu as compris mon architecture, et ce que tu dis prends énormément de sens, Merci. J’ai oublié de préciser que le delete ElementA (qu’il ne faut pas faire ^^) n’aurait pu se produire qu’a la fermeture de mon programme, dans mon cas. Je n’aurai donc jamais pu manipuler l’objet après.
    Et effectivement, dans cette architecture, tout appartient à CFenetre. C’est lui qui manipule le tout (de façon direct avec l'utilisateur), c’est donc lui qui possède tout .

    PS : J’ai oublié de préciser que j’utilisais des pointeurs, car je manipule en fait des dizaines de milliers d’éléments, j’espère atteindre les centaines de millier (mais bon on verra pour ça). Et donc, dites moi si je me trompe, mais il est beaucoup plus rapide et léger d’envoyer en paramètre des pointeurs que des objets, surtout a grosse échelle, non ? ^^

    Bests.

  6. #6
    Membre très actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Par défaut
    Bonjour Eagl1,

    Pour revenir sur tes précédents points, en détruisant l'objet, comme l'a dit Niark13, tu t'exposes à des erreurs de segmentation si tu essais après de détruire ou de libérer la mémoire allouée à un objet membre (objet en attribut dans une autre classe)de cet objet déjà détruit (les objets ou attributs d'une classe ont une durée de vie égale à la classe il me semble, en tout cas pour sur, jamais supérieure s'il ne sont pas statiques).

    L'utilisation de pointeurs dans ton cas est bien sur fortement recommandé car cela te permet dans un premier temps d'éviter les erreurs comme tu as connu (invariance inattendue des valeurs affichées) qui sont liées au fait que les objets que tu passes en paramètre à tes fonctions sont en fait passés en copie (c'est-à-dire qu'une copie du paramètre est créée spécialement pour ta fonction et c'est elle qui subit le code de ta fonction). L'utilité dans ce cas de passer un pointeur est qu'un copie d'un pointeur affectera forcément le même objet (vu que l'adresse est la même). Ensuite, imaginons que tes objets CElements soient très très lourds, imagine ce que cela donnerait des copies de ces objets à chaque appel de tes fonctions et pour chaque objet passé en paramètre (des milliers dans ton cas) ? un pointeur a l'avantage d'être très léger (4 octets il me semble mais à demander aux autres plus expérimentés que moi qui t'ont répondu).

    Cordialement,

    Edit : les conseils de Pyros sont encore plus avisés

  7. #7
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 615
    Par défaut
    il est beaucoup plus rapide et léger d’envoyer en paramètre des pointeurs que des objets, surtout a grosse échelle, non ? ^^
    Juste à propos de cette phrase, si ton seul soucis est un problème de perf, tu peux les passer par référence (constante ou pas selon si tu as besoin de modifier l'objet d'entrée). C'est toujours moins dangereux que de passer des pointeurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void fonction1(HeavyClass heavyObject);
    void fonction2(const HeavyClass& heavyObject);
    ...
    HeavyClass heavyObject;
    fonction1(heavyObject); // copie de heavyObject pour le passer à la fonction
    fonction2(heavyObject); // pas de copie
    Ainsi, heavyObject n'est pas copié.

    Note: les compilo actuels sont censés éviter ce genre de copies inutiles (je ne me souviens jamais de l'acronyme, mais ce mécanisme porte un nom), cependant je préfère passer encore par ref const.

    Une autre solution est d'utiliser les smart pointeur (boost smartPtr par ex.), à peine plus lourds qu'un pointeur et tellement plus safe

  8. #8
    Membre averti
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 31
    Par défaut
    Merci Kaamui,
    Tu confirmes et développes exactement ce que je pensais lorsque je disais "rapide et léger" dans mon PS.

    Ha mais ce n’est pas bête les références, mais pourquoi je n’y ai pas pensé, j’essaie de suite. Car quelque part, je me sentais un peu mal à l’aise avec un envoie de pointeur en paramètre, et la copie de ce pointeur après.
    (je ne connaissais pas les smart pointeur, je regarderai ca un peu après, j’essaie déjà de faire un truc qui marche, aussi bourrin puisse t il l’être ^^)
    Merci.
    Eagl

  9. #9
    Membre averti
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 31
    Par défaut
    Yop,
    Bon ben pour conclure cette discussion, je n’ai pas utilisé le passage par référence. Ceci dit j’ai fait quelque chose de très proche, c’est un passage par adresse, ça marche nickel. Donc oui j’ai toujours un pointeur dans ma classe CAlgo mais aucun new n’est fait nulle part et donc aucun delete n’est nécessaire, je me sens plus confortable, lol.
    Je vous remercie à tous pour vos remarques, elles étaient constructives.

    See you in the next thread. (ou ici si des gens on des choses à rajouter )

  10. #10
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 615
    Par défaut
    Tu donne l'adresse d'une variable locale ? O_o
    Un truc dans ce gout là ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CElement Element(Variables) ;
    CAlgo Algo(Variables) ;
    Algo.LinkClass(&Element)
    Si c'est le cas, ça me parait très dangereux, c'est la porte ouverte à plein de segfault.
    D'une manière général, les pointeurs et autres adresses mémoire ne devraient être utilisés que pour compat avec une API plus bas niveaux (genre du C), ou un réel besoin de perf, et encore... En C++ y'a suffisamment de moyen de s'en passer (smartPtr et autre).

    Enfin, si c'est pour du dev perso, c'est pas le peine de trop se prendre la tête non plus

    Et juste un petit détail sur la forme:
    - Les constructeurs commencent par une majuscule
    - Les variables par une minuscule
    - Les attributs de class par m_ (m comme membre)
    - Les fonctions par une minuscule

    Tu verra, ton code deviendra beaucoup plus clair

  11. #11
    Membre averti
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 31
    Par défaut
    Salut,
    Oui c'est comme ca que je faisais. Je sais que ca peut être dangereux, mais c’est quand même moins dangereux que ma première façon de faire . Tu remarques que j’ai dit "faisais", car très tard hier soir (ou plutôt, très tôt ce matin), j’ai eu une illumination, et j’ai réussi à faire ce que je voulais finalement sans pointeur et ni référence. Ceci dit pour des problèmes de performance (c’est un moteur de particules, donc les perfs me seront importantes), je pense que je n’y échapperai pas plus tard à ce genre de code.
    C’est certes un programme personnel, mais je compte le montrer à des professionnels pour trouver du travail, (faut bien prouver ses compétences algorithmiques,^^) donc bon.

    PS : dans mon code je respecte déjà tes conseils sur la forme. C’est juste quand je fais du pseudo code, je ne sais pas pourquoi, je ne le respect plus, :\.

    Merci beaucoup pour ton intérêt en tout cas.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 15/08/2012, 10h37
  2. Aide pointeur / type de variable char.
    Par enzo68290 dans le forum C
    Réponses: 3
    Dernier message: 14/04/2012, 11h03
  3. Réponses: 6
    Dernier message: 31/03/2011, 08h55
  4. [déclaration de variable]Pointeur
    Par ronan99999 dans le forum C
    Réponses: 6
    Dernier message: 04/10/2005, 15h53
  5. Réponses: 6
    Dernier message: 30/06/2005, 14h19

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