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 :

probleme de comprehension au niveau de pointeur


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2020
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2020
    Messages : 11
    Par défaut probleme de comprehension au niveau de pointeur
    salut,

    il s'agit de la définition de deux constructeurs

    j'arrive pas a comprendre pourquoi allouer de l'espace mémoire alors que nous pouvons utiliser la notion d'address

    en vérité j'aimerai savoir qu'est ce qui différencie ses deux constructeur ci dessous

    NB:largeur et hauteur sont des pointeurs

    1-cas: Rectangle::Rectangle(double l,double h):largeur(new double(l)),hauteur(new double(h))

    2-cas: Rectangle::Rectangle(double l,double h):largeur(&l),hauteur(&h)

    merci d'avance

  2. #2
    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
    Le premier crée des pointeurs pour y stocker les valeurs, le second pointe vers les variables passées en paramètres.
    Et vu que les variables sont temporaires, il pointera vite vers de la mémoire pourrie.
    Dans les deux cas, avoir un pointeur comme membre ici est pas loin du top 1 de la mauvaise idée.
    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.

  3. #3
    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,

    En fait, les deux sont complètement aberrant en l'état, car les notions de hauteur et de largeur devraient être manipulées par valeurs

    En effet, un pointeur n'est, à la base, qu'une valeur numérique entière (généralement) non signée qui permet de représenter l'adresse à laquelle on espère trouver une donnée du type indiqué.

    Ce concept n'a qu'un seul intérêt: on dispose d'une valeur (nullptr, anciennement, on utilisait la macro NULL qui indique de manière explicite que ... la donnée souhaitée n'existe pas.

    Or, dans le cas de la hauteur et de la largeur d'un rectangle, cela revient, sommes toutes, à dire que la donnée en question est égale à 0. Et tu seras d'accord avec moi pour dire qu'avoir un rectangle dont hauteur est égale à 0 et la largeur est égale à 3.1415 (ou l'inverse) n'a ... absolument auun sens !

    Ceci étant dit, pour les cas pour lesquels l'utilisation aurait du sens (car il y en a), il faut savoir que C++ applique des règles très strictes quant à la durée de vie des données:

    De manière générale, une donnée -- quelle qu'elle soit -- n'existe dans l'application qu'entre le moment où elle est déclarée et l'accolade fermante qui correspond à la dernière accolade ouvrante qui précède cette déclaration (on parle de "portée" des variables).

    Voici un petit exemple pour t'aider à comprendre (lis les commentaires :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main(){
        int a = 3;   // a existe à partir d'ici
        // on peut utiliser a ici
        for(/* ... ; ...; ... */){
            int b;  // b existe à partir d'ici
            int c;  // c  existe à partir d'ici
            //  on peut utiliser a, b et c ici, car les trois existent
        }  // b et c sont détruits ici (c est détruit en premier, b est détruit ensuite)
        // on peut toujours utiliser a ici
        // mais on ne peut plus utiliser ni b ni c.
    } // a est détruit ici
    Le problème avec les pointeurs, c'est qu'il n'y a aucun moyen de faire la différence entre une adresse mémoire à laquelle on trouvera effectivement la donnée du type indiqué et la même adresse mémoire dont la donnée a déjà été détruite. Voici un code pour comprendre le problème:
    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
    21
    int main(){
        int * ptr_b = nullptr; // pointeur dont on dit explicitement
                               // qu'il pointe sur une adresse invalide
        /* on peut tester */
        if(! ptr_b){ // correspond à if(ptr_b == nullptr)
            std::cout<<"adresse invalide\n";
        }
        for(/* ... ; ...; ... */){
            int b = 5;
            ptr_b = & b;  // ptr_b prend l'adresse mémoire où se trouve b
            *ptr_b = 10; // remplace la valeur qui se trouve à l'adresse indiquée
                       // par ptr_b (autrement dit la valeur de b)
                       // par 10, pas de problème
         }  // CRACK!!! b est détruit, ptr_b contient une adresse mémoire à laquelle
            // on ne trouve plus la moindre donnée
        if(ptr_b){ // correspond à if(ptr_b != nullptr)
            std::cout<<"ptr_b semble correspondre à une adresse valide\n";
            *ptr_b = 15; // BOUM: l'adresse semble valide, et pourtant
                         // elle ne correspond à aucune donnée
        }
    }
    L'allocation dynamique de la mémoire nous permet de dire au compilateur que l'on veut "contourner" la règle sur la portée des données. En d'autres termes, elle nous permet de dire au compilateur que
    Je ne veux pas que cette donnée soit détruite au moment où on quitte la portée dans laquelle elle est déclarée.
    Il est parfois utile de pouvoir agir de la sorte, mais, en toute honnêteté, cela pose souvent bien plus de problèmes que cela n'en résout, parce que:
    1. Il faut s'assurer de manière systématique que le pointeur représente une adresse mémoire valide avant d'essayer d'accéder à la donnée qui s'y trouve cela implique
    2. qu'il faut avoir la certitude que le pointeur reprend la valeur nullptr lorsque la donnée est effectivement détruite (surtout si le pointeur reste accessible après la destruction)
    3. nous prenons spécifiquement la responsabilité de veiller à libérer la mémoire allouée de manière dynamique, ce qui implique:
    4. qu'il faut libérer cette mémoire au plus tard juste avant de "perdre" l'adresse mémoire (le dernier pointeur pointant sur l'adresse mémoire en question), autrement, nous observerons une "fuite mémoire", qui, à termes, pourrait mettre l'intégrité de tout le système à mal
    5. il faut éviter de libérer "une deuxième fois" la mémoire (allouée de manière dynamique) qui a déjà été libérée une première fois, car cela fera planter l'application

    A tel point qu'il n'y a -- en définitive qu'un seul cas dans lequel nous n'aurons pas d'autre choix que d'avoir recours à l'allocation dynamique de la mémoire: lorsque l'on définit une hiérarchie de classes (polymorphes) et que l'on souhaite maintenir toutes les instances des classes participant à cette hiérarchie sous la forme d'une "liste d'objets connus comme étant du type de base".

    Et encore, selon le cas, nous veillerons à utiliser les pointeurs intelligents fournis -- depuis 2011 -- par la bibliothèque standard (avant, nous aurions utilisés ceux fournis par boost, dont la bibliothèque standard s'est inspirée), à savoir : std::unique_ptr ou le couple std::shared_ptr et std::weak_ptr.

    Mais ca, j'en parlerai un autre jour
    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

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2020
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2020
    Messages : 11
    Par défaut probleme de comprenhension sur les class et allocation dynamique
    salut,
    j'aimerai aussi que vous m'aider a ce niveau avec le code ci dessous

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //declaration
    vector<Vehicule*> listeVehicules;
    listeVehicules.push_back(new Voiture(15000, 5));
    j'aimerai savoir s'il est possible d'utiliser listeVehicules.push_back(& v) après avoir déclarer Voiture v(15000,5) Voiture etant une classe; cet a dire ecrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
    vector<Vehicule*>listeVehicules;
    Voiture v(15000,5);
    listeVehicules.push_back(&v);
    }
    merci d'avance

  5. #5
    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
    Il est possible de le faire (dans le sens où le compilateur ne verra aucune objection), car un pointeur n'est jamais qu'une valeur numérique entière (généralement) non signée représentant l'adresse mémoire à laquelle on devrait trouver une donnée du type indiqué.

    Mais, en pratique, les règles de portées pour les données créées sur la pile (les données créées sans utiliser new) font qu'il est très largement déconseillé de le faire, parce que le pointeur risque fort de représenter une adresse mémoire où se trouve une donnée qui a déjà été détruite (et qu'il n'y a aucun moyen de faire la différence entre cette adresse mémoire et une autre à laquelle se trouve une donnée qui existe encore et qui n'a pas été détruite).

    Voici un exemple simple pour te faire comprendre:
    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
    int main(){
        std::vector<Voiture*> tab;
        for(int i=0; i<10; ++i){ // on veut ajouter 10 voiture
            Voiture v;
            tab.push_back(&v); //CRACK
        } // v est détruit ici,
          // le pointeur correspondant dans tab pointe sur une
          // adresse invalide
        for(auto * it : tab){
            it->someFunction(); // BOOM: erreur de segmentation:
                                // on essaye d'accéder à une
                                // adresse mémoire qui ne
                                // contient aucune donnée non détruite
        }
    } tab est détruit ici
    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

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2020
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2020
    Messages : 11
    Par défaut pointeur et allocation dynamique
    Citation Envoyé par Bousk Voir le message
    Le premier crée des pointeurs pour y stocker les valeurs, le second pointe vers les variables passées en paramètres.
    Et vu que les variables sont temporaires, il pointera vite vers de la mémoire pourrie.
    Dans les deux cas, avoir un pointeur comme membre ici est pas loin du top 1 de la mauvaise idée.
    il pointera vers la memoire pourrie sachant que dans le destructeur on a largeur=nullptr; hauteur=nullptr;????

  7. #7
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 763
    Par défaut
    Citation Envoyé par adda_issa Voir le message
    il pointera vers la memoire pourrie sachant que dans le destructeur on a largeur=nullptr; hauteur=nullptr;????
    Non, il y a erreur de compréhension Le pointeur va pointer vers une adresse qui ne sera plus utilisée par ton objet (donc à l'instant T, tu n'as plus la garantie que ton pointeur pointe vers l'objet désiré ou vers tout autre chose - c'est indéterminé (*))

    Le destructeur est surtout en charge de libérer la mémoire que l'objet a allouée.

    Pour largeur=nullptr; hauteur=nullptr, ce sont des affections, juste pour mettre la mémoire à zéro. C'est un héritage du C, justement lorsque tu as des pointeurs invalides - en voyant tout à 0 ou que ton programme détecte le pointé à 0 (cela peut être un plantage si tu ne fais pas les tests ), tu dois te dire qu'il y a un problème parce que le destructeur a été appelé. Au lieu que ton programme ait des objets erronés ou pas (mais c'est indéterminé (*)) sans vraiment planter (c'est 1 principe du développeur - toujours s'arrêter à l'endroit du bogue et "pas ailleurs")

  8. #8
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 763
    Par défaut
    Citation Envoyé par adda_issa Voir le message
    il pointera vers la memoire pourrie sachant que dans le destructeur on a largeur=nullptr; hauteur=nullptr;????
    Suite à ton message privé, je te conseille vivement de reprendre la notion de pointeur parce que c'est très très mélangé dans ta tête

    1) la notion d'adresse et l'opérateur &.
    2) les variables locales, leurs allocations et après les "dangling pointers" que @koala01 te parlait
    3) l'allocation dynamique avec les fonctions malloc/ free.
    3) les structures et leurs allocations/ comment les membres sont "agencés en mémoire" - parce que j'ai compris que tu me parles de cela, mais je ne vois pas le rapport avec la choucroute
    4) toutes les autres choses en relation avec la mémoire en C que j'oublie

    Et seulement ensuite et après du code très plantogéne mais très instructif qui forge l'expérience , tu pourras aborder le C++ et la notion de constructeur/ destructeur dont je te parlais dans le message précédent
    Il y a aura d'autres choses en C++ comme par exemple les références, les pointeurs intelligents.

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

Discussions similaires

  1. probleme de comprehension pointeurs*
    Par J3ChEn dans le forum Débuter
    Réponses: 5
    Dernier message: 10/06/2010, 16h21
  2. Probleme de comprehension de la fonction Header
    Par glycerine dans le forum Langage
    Réponses: 3
    Dernier message: 07/08/2006, 11h30
  3. Probleme de comprehension de code
    Par joxbl dans le forum Langage
    Réponses: 2
    Dernier message: 30/05/2006, 19h58
  4. Réponses: 17
    Dernier message: 24/03/2005, 12h24
  5. [ADODB]probleme de comprehension
    Par flogreg dans le forum ASP
    Réponses: 2
    Dernier message: 15/11/2004, 16h15

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