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 :

les objets sont-ils des pointeurs ?


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    août 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 28
    Points : 20
    Points
    20
    Par défaut les objets sont-ils des pointeurs ?
    Bonjour a tous !

    j'ai un soucis de compréhension au niveau des objets en c++... Je suis plus habitué au java, et c'est ma premiere en c++, alors peut-etre que ma question va paraitre simple en fait ^^

    Juste pour replacer le contexte : je travaille avec memcached, une librairie en développée en C qui permet d'utiliser un serveur de mémoire cache (qui se comporte comme une table de hachage). Les prototypes des deux fonctions principales sont les suivants :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    memcached_return_c rc = memcached_set(..., char* key, size_t key_length, char* value, size_t value_length, ...)
    char * value = memcached_get(..., char* key, size_t key_length, size_t * value_length, ...)
    les objets stockés sont passés en paramètre sous forme de pointeurs de chaines de caractères (cast).
    Seulement voila... Certains objets contiennent eux-même des attributs, etc, qui sont soit des pointeurs, soit autre chose, et la memcached memcached_set stocke tout, donc même les pointeurs, sans s'occuper de ce qui est pointé par le pointeur.

    Tout ca pour en venir a ma petite question ^^
    Quand je déclare un objet par exemple avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObject c = new MonObject()
    std::string c ("blabla")
    ou bien quand j’accède a un attribut d'une classe (qui est protected, ou via un getter),

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObject c = monInstance.getter()
    MonObject c = monInstance.parametre
    qu'est-ce que j'obtiens ? un pointeur, ou autre chose ? comment est représenté la memoire : est-ce que je dois faire pour pouvoir accéder a la zone mémoire qui contient effectivement l’objet lui-même ? Et est-ce la même chose pour les objets string ? Tout ça est un peu confus pour moi qui habituellement fait du java, je ne suis pas sur de faire la différence (au niveau de la gestion de la memoire) lorsqu’on utilise un struct et lorsqu'on utilise un objet ^^

    merci a vous

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 696
    Points : 30 555
    Points
    30 555
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    pour faire rapide : imagine la mémoire comme un grand tableau.
    Chaque case du tableau est identifiée par son adresse mémoire.
    Chaque case du tableau peut contenir un élément
    - un type basique (int, bool, ...)
    - un type complexe (struct/class) (où chaque membre sera attribué lui-même dans une case)
    - une adresse d'une autre case (y compris d'elle-même mais là c'est "inutile" ?^^) : le fameux pointeur

    Quand tu écris MonObjet m; la mémoire pour stocker m est créée sur la stack.
    La particularité de la stack est que dès qu'on sort de son scope l'objet est supprimé.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    {
      MonObjet m;
      m.doSomething();
    }
    m.doSomething(); // compile error
    Dans ce cas tu peux récupérer le pointeur vers m via &m mais pour utiliser ce pointeur il faut s'assurer que l'objet pointé (m) existe toujours. Sinon ça crash.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    MonObjet* ptrm;
    {
      MonObjet m;
      ptrm = &m;
      // les 2 lignes suivantes sont identiques
      m.doSomething();
      ptrm->doSomething();
    }
    ptrm->doSomething(); // ça compile, ça crash à l'exécution
    Quand tu écris MonObjet* m = new MonObjet; la mémoire pour stocker m est créée sur la heap, et m est un pointeur vers cette mémoire.
    La heap n'est pas supprimé automatiquement, il faut la supprimer explicitement (via delete dans ce cas) grâce au pointeur que l'on possède.
    Dans le cas où tu trimballes le pointeur, il faut s'assurer que l'objet pointé existe toujours également.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    MonObjet* ptrm = new MonObjet;
    MonObjet* ptrm2 = ptrm;
    // les 2 lignes suivantes sont identiques
    ptrm->doSomething();
    ptrm2->doSomething();
    delete ptrm;
    ptrm->doSomething(); // crash
    ptrm2->doSomething(); // crash

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObject c = new MonObject()
    std::string c ("blabla")
    Tu ne pourras pas écrire ce code, parce que c est redéfini.
    Le premier c sera un pointeur vers un objet MonObjet;
    le second est un objet créé sur la stack.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObject c = monInstance.getter()
    MonObject c = monInstance.parametre
    Même début, mais là ça dépend du getter.
    Si le getter retourne un const& (ce qui est généralement le cas d'un getter bien écrit pour retourner un type complexe), il y aura une copie d'effectuée.

    qu'est-ce que j'obtiens ? un pointeur, ou autre chose ? comment est représenté la memoire : est-ce que je dois faire
    Tant que tu ne vois pas de *, il ne s'agit pas d'un pointeur. Sauf à utiliser les smart_pointer.
    L'opérateur pour récupérer l'adresse d'une variable est & .
    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
    Membre éclairé

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

    Informations forums :
    Inscription : mai 2005
    Messages : 264
    Points : 710
    Points
    710
    Par défaut
    Effectivement, en Java, tu ne manipules jamais un objet directement, tu emploies une référence, qui elle est un lien vers l'objet.

    Attention, le terme référence ci-dessus doit s'entendre au sens Java du terme, pas au sens C++. Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // Code Java
    Maclasse obj; // crée une référence vers un objet de type Maclasse et l'initialise à null
    obj = new Monobjet(); // instancie un objet de type Maclasse qui est referencé par la variable obj
    obj.coucou(); // appel de la méthode coucou de l'objet référencé par obj
    En C++, par défaut, tu peux manipuler un objet directement (par valeur). Exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // Code C++
    Maclass obj; // Crée un objet de type Maclasse en appellant son constructeur par défaut
    obj.coucou(); // appel de la méthode coucou de l'objet obj
    Dans ce cas-là, la variable obj contient directement l'objet. Comme toutes les variables automatique, elle sera détruite à la fin du bloc courant (en appellant le destructeur de Maclasse). obj n'est pas une référence à un objet situé ailleurs.

    Tu as également la possibilité de créer dynamiquement ton objet sur le tas avec new, comme tu le fais en Java. En C++, new renvoie un pointeur vers l'adresse mémoire de l'objet nouvellement créé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Maclasse* obj = NULL; // obj est un pointeur qui ne pointe sur rien
    obj = new Maclass; // on alloue de la mémoire et on construit un objet de type Maclasse. obj contient l'adresse de cet objet. 
    obj->coucou(); // appelle la méthode coucou de l'objet pointé par obj
    delete obj; // détruit l'objet pointé par obj (appel de destructeur) et libération de la mémoire réservée pour celui-ci.
    Comme tu le vois, obj est explicitement déclaré comme étant un pointeur et l'appel de méthode utilise l'opérateur flèche au lieu du point. Si j'avais écris, comme tu l'as fait, j'aurais eu les erreurs de compilation suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Maclasse obj = new Maclasse(); // Erreur impossible de convertir un Maclasse* en Maclasse.
    obj.coucou(); // erreur, le pointeur obj ne possède pas de membre coucou (c'est l'objet pointé qui en possède un).
    Donc, quant à ta question sur ce qui est renvoyé par tes getters, tout dépend de leur signatures. Ils peuvent renvoyer un objet, une référence à un objet, ou encore un pointeur vers un objet. Regarde simplement quel est leur type de retour.
    "By and large I'm trying to minimize mentions of D in C++ contexts because it's as unfair as bringing a machine gun to a knife fight." - Andrei Alexandrescu

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    août 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    merci beaucoup pour ta réponse !! C'est beaucoup plus clair, mais il me reste encore quelques question

    Par exemple quelle est la différence entre écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObject c = new MonObject()
    et écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObjet* ptrm = new MonObjet;
    ?

    Je ne sais pas si je me représente bien, mais si je veux "accéder a la zone mémoire ou est réellement stocke l'objet" (c'est toujours dans l'optique de ne pas me perdre avec des pointeurs quand je stocke des choses avec memcached), mais je comprends ça (avec des notations pas tres bien choisies, mais c'est pour donner l'idee : la fleche represente le fait de "pointer"):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    c -> la zone memoire ou est stockee l'objet
    ptm -> un autre pointeur -> la zone memoire ou est stockee l'objet
    et donc, si je veux toujours "accéder a la zone mémoire ou est réellement stocke l'objet", est-ce que ca a du sens de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObject c = new MonObject();
    *c;
    Donc du coup, comme j'utilise le template pair defini dans la librairie standard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <class T1, class T2> struct pair
    {
      typedef T1 first_type;
      typedef T2 second_type;
     
      T1 first;
      T2 second;
      pair() : first(T1()), second(T2()) {}
      pair(const T1& x, const T2& y) : first(x), second(y) {}
      template <class U, class V>
        pair (const pair<U,V> &p) : first(p.first), second(p.second) { }
    }
    si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::pair <std::string,std::string> cntWithKey (key,cnt);
    comme les deux membres sont des classes, toujours a cause de memcached qui gere mal les pointeurs, si je veux reelement recuperer ce qui est en memoire, je dois faire qqchose comme ça ?
    merci beaucoup pour vos explications !!!

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    août 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Merci beaucoup Niark13, desole j'ai commence a repondre alors que tu n'avais pas encore repondu ^^

    Ok maintenant j'ai encore mieux compris, c'est la difference entre
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObject c = new MonObject()
    que je n'avais pas saisis.

    Et donc, par exemple avec le template pair,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <class T1, class T2> struct pair
    {
      typedef T1 first_type;
      typedef T2 second_type;
     
      T1 first;
      T2 second;
      pair() : first(T1()), second(T2()) {}
      pair(const T1& x, const T2& y) : first(x), second(y) {}
      template <class U, class V>
        pair (const pair<U,V> &p) : first(p.first), second(p.second) { }
    }
    si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    str::string cnt ("blaba");
    str::string key ("123456789");
    std::pair <std::string,std::string> cntWithKey (key,cnt);
    je suis sur que je cntWithKey contient toute l'information, sans pointeurs ? (Ca ne m'arange pas, parce que ca plante a ce niveau ^^ comme je programme dans un projet beaucoup plus vaste, je n'ai acces qu'a une fonction de log pour unique aide au debuggage, je ne peux pas savoir exactement quel est le soucis ^^ mais par elimination, je croyais que le crach venait du fait que pair etait un couple de pointeurs, et pas un couple contenant bien les deux objets au complet...)

    merci encore

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 696
    Points : 30 555
    Points
    30 555
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Rhyos Voir le message
    Par exemple quelle est la différence entre écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObject c = new MonObject()
    et écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObjet* ptrm = new MonObjet;
    ?
    La première écriture te renverra une insulte du compilateur.*
    Essayer de compiler c'est un premier pas pour savoir ce qui est correct ou non. Si la syntaxe est mauvaise à la base, ça sert à rien d'aller plus loin.

    * en supposant que MonObject n'est pas un typedef farfelue qui camoufle un pointeur.
    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
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : février 2009
    Messages : 762
    Points : 1 392
    Points
    1 392
    Par défaut
    Pour un utilisateur venant du Java, j'ai tendance à conseiller de ne pas utiliser new dans un premier temps. Jusqu'à ce que tu en ressentes vraiment la nécessité, et même à ce moment, il se pourrait que d'autres alternatives s'offrent à toi. Donc pour passer en paramètre et éviter la copie, utilise les références (au sens C++ du terme) : void fonction(std::vector<int> &un_vecteur);.

    D'ailleurs, je me souviens que dans un livre C++ (Accelerate C++), il ne parle des pointeurs que vers le chapitre 10-11. Comme quoi, ce n'est pas spécialement la première chose à apprendre/utiliser en C++.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    août 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Merci pour vos réponses, je pense avoir bien compris maintenant
    Bousk désolé de ne pas avoir testé, mais ayant été un peu perdu et en train de travailler aussi, je n'ai pas eu le temps pour ca

    en tout cas merci a tous
    je marque resolu

  9. #9
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Citation Envoyé par Rhyos Voir le message
    je suis sur que je cntWithKey contient toute l'information, sans pointeurs ? (Ca ne m'arange pas, parce que ca plante a ce niveau ^^ comme je programme dans un projet beaucoup plus vaste, je n'ai acces qu'a une fonction de log pour unique aide au debuggage, je ne peux pas savoir exactement quel est le soucis ^^ mais par elimination, je croyais que le crach venait du fait que pair etait un couple de pointeurs, et pas un couple contenant bien les deux objets au complet...)
    Oui et non : les objets std::string contiennent des pointeurs, eux. Si tu les utilises normalement, ça ne pose pas de problème puisqu'ils ont un constructeur de copie et un opérateur d'affectation qui se charge de gérer correctement ces pointeurs, mais si tu fais une copie "brute" bit par bit (et c'est, si j'ai bien compris, ce qui se passe dans la bibliothèque memcached), ça peut tout à fait ne pas fonctionner (la mémoire pointée utilisée en interne par std::string peut avoir été libérée).

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

Discussions similaires

  1. Les développeurs sont-ils des destructeurs d’emploi ?
    Par Hinault Romaric dans le forum Débats sur le développement - Le Best Of
    Réponses: 450
    Dernier message: 09/09/2020, 10h08
  2. Les développeurs sont-ils des destructeurs d’emploi ?
    Par Hinault Romaric dans le forum Actualités
    Réponses: 345
    Dernier message: 05/05/2013, 17h20
  3. Les ingénieurs sont-ils des machines humaines ?
    Par Hinault Romaric dans le forum Actualités
    Réponses: 51
    Dernier message: 12/02/2013, 23h46
  4. Les composants graphiques sont-ils des controles ActiveX
    Par Lucas Panny dans le forum C++Builder
    Réponses: 0
    Dernier message: 02/11/2007, 05h55

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