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 :

Passage en référence d'un pointeur sur un tableau


Sujet :

C++

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Points : 218
    Points
    218
    Par défaut Passage en référence d'un pointeur sur un tableau
    Bonjour,

    voilà, je ne suis pas une pro du C++
    et j'ai un peu mal avec les pointeurs...


    Donc voilà, je voudrais créer une méthode qui ait en argument un pointeur sur un tableau, que je passe en référence
    je sais pas si je m'explique bien
    mais en tous cas, j'ai un peu du mal à voir comment m'y prendre

    Donc, je voudrais une méthode du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    MaMethode(int &size, MaClasse *monTableau)
    {
        //je recherche le nombre d'éléments...
        // j'affecte le nombre d'éléments à la variable 'size'
     
        // ensuite, j'alloue le tableau
        monTableau = (MaClasse*)malloc(size * sizeof(MaClasse));
     
        // et puis, j'affecte les éléments du tableau
        for (int i = 0; i<size; i++)
        {
            monTableau[i] = ...
        }
    }
    cette méthode me permettrait de remplir 'monTableau',
    mais je ne sais pas à l'avance combien d'élément il contiendra
    c'est pourquoi, je passe également la taille en référence, pour l'avoir en retour quand j'appelle ma méthode...

    donc, je ne sais pas si je m'y prends bien...

    bon voilà,
    j'espère que vous m'aurait comprise
    et que vous pourrez m'aider un peu

    Merci,
    à +

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 141
    Points : 12 242
    Points
    12 242
    Par défaut
    Moi, je passerais une référence sur une instance de std::vector et pas un tableau.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Bonjour,
    Réponse courte: void MaMethode(int size, MaClasse * &monTableau)
    Réponse élaborée: Celle de bacelar: Il est mieux d'utiliser un std::vector.

    PS: En C++, utiliser new[] et delete[] plutôt que malloc() et free()... Surtout pour des classes.
    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.

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Points : 218
    Points
    218
    Par défaut
    OK merci à vous deux

    je vais commencer par la version courte de Médinoc
    je ne connais pas les std::vector

    je vous tiens au courant

    à +

  5. #5
    Membre averti Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Points : 417
    Points
    417
    Par défaut
    Bonjour,
    Tout d'abord, je pense que le mieux c'est de ne pas utiliser malloc, mais new (j'avais commencé à tapper avant).
    (on laisse malloc et les char* aux mecs qui font du C, maintenant on est grand )
    Maintenant concernant plus précisement ton problème : plusieurs choses.
    Il y a plusieurs manières de passer une variable à une fonctions, 3 :
    Par valeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Func(MaClasse Objet);
    Par réference :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Func(const MaClasse& Objet);
    Par pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Func(MaClasse* pObjet);
    J'ai mis exprès, une réference constante et je vais expliquer pourquoi après.
    Dans le premier cas, la variable Objet est copiée puis posée dans la pile d'appel.
    Dans le second cas, la variable Objet est est posée dans la pile d'appel, il n'y a donc pas de copie de la variable Objet de faite
    Et enfin dans le dernier cas, on va déposer l'adresse de la variable Objet dans la pile d'appel. On copie l'adresse (équivalent à copier un int)
    Je vais expliquer maintenant dans quelles occasions j'utilise quoi. (Tout le monde ne va surement pas être d'accord, mais bon)
    Si ma class n'est pas un type de base (int, long, float etc...), je n'utilise jamais le premier type car l'objet va être copié, autant le passer en référence constante, même résultat et pas de copie (tu as accès à la variable, mais elle n'est pas copiée). Ensuite, je choisi le second cas quand la fonction n'est pas destinée à modifier la variable Objet. Le cas, où on a une structure avec des informations à lire dedans, (référence constante = read only).
    Et tu l'auras surement deviné, quand la fonction est destinée à modifier la variable Objet, alors je passe cette variable par pointeur.
    Pour ce qui est des types de base, si la fonction est destinée à les modifier, par pointeur, sinon par valeur (mettre dans la pile d'appel un int ou sa copie, c'est pareil).
    J'en viens maintenant au code que tu as tappé. Et j'espère que mes explications vont t'avoir servies.
    Ta fonction MaMethode, est destinée à modifier, un tableau de MaClass. (Oui il serai mieux d'utiliser un vector, j'en parle apres :p). Donc je passerai un pointeur sur un tableau. Comme ce tabeau est dynamique, c'est un pointeur sur un Objet de type MaClass MaClass**. Pour allouer la mémoire, tu as besoin de la taille du tableau. Tu passais cette taille par réference, je la passerai plutôt par valeur (type de base que l'on ne veut pas modifier).
    La signature serai donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void MaMethode(size_t Size, MaClasse** ppMonTableau);
    Ainsi l'utilisateur voit que tu vas chercher à modifier ppMonTableau, et pas Size.
    Pour le code complet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void MaMethode(size_t Size, MaClasse** ppMonTableau)
    {
        if (ppMonTableau) // Il ne faut pas que l'utilisateur nous ai passé un pointeur NULL
        {
            *ppMonTableau = new MaClasse[Size];        
        }
    }
    Maintenant, tout comme pour le new et les char*, les tableaux en C++ c'est plus trop recommandé. Il y a pour cela dans la bibliothèque standard les vectors. Il s'agit de l'équivalent, en mieux, des tableaux ^^
    Et donc avec l'utilisation d'un vector :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void MaMethode(size_t Size, std::vector<MaClasse>* pMonTableau)
    {
        if (pMonTableau) // Pareil que tout à l'heure
        {
            pMonTableau->resize(Size);
        }
    }
    Si tu utilise le polymorphisme dans a classe MaClasse, alors tu devras non pas utiliser un std::vector<MaClasse>, mais un std::vector<MaClasse*> et donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void MaMethode(size_t Size, std::vector<MaClasse*>* pMonTableau)
    {
        if (pMonTableau) // Pareil que tout à l'heure
        {
            pMonTableau->resize(Size);
            for (size_t i = 0, i < pMonTableau->size(), ++i)
                (*pMonTableau)[i] = new MaClasse;
        }
    }
    Voila je pense que j'ai été assez complet la ^^
    Première grosse démo en construction :
    http://bitbucket.org/rafy/exo2/

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Tu as oublié de préciser que quand un paramètre de sortie n'est pas optionnel, il est recommandé de le passer par référence non-constante plutôt que par pointeur: Cela rend le code de la fonction plus lisible, sa déclaration plus explicite (vu qu'une référence ne désigne jamais un tableau) et dispense du test de NULL.

    Venant du C, j'ai longtemps cru que ça rendait le code de l'appel moins compréhensible/lisible. Mais on prend vite le réflexe, surtout si on a un bon EDI (et des fonctions bien documentées, et const quand il le faut).
    Et puis, si on commence par le C++ ou si on vient du VB, on a le réflexe dès le début.

    Si vous n'aimez pas le passage par référence "implicite" comme ça, passez au C#.
    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.

  7. #7
    Membre averti Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Points : 417
    Points
    417
    Par défaut
    Je ne l'ai pas précisé car je ne le fait jamais ^^. Comme je l'ai dis c'est ma manière de faire, et surement d'autre font autrement.
    Ceci dis, je trouve que ta remarque est plutôt bonne, et que ca guide encore plus l'utilisateur...
    Première grosse démo en construction :
    http://bitbucket.org/rafy/exo2/

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Points : 218
    Points
    218
    Par défaut
    Whahou!!
    Merci Rafy pour avoir consacrer un peu de ton temps à ces explications.

    Par contre, je sais pas trop si tu as fait attention
    (où peut être que c'est moi qui ait du mal à comprendre ce que tu a mis)
    mais à l'appel de ma méthode, je ne connais pas le nombre d'éléments que contiendra mon tableau au retour,
    c'est pourquoi je pensais passer en référence la taille...

    dans ce cas, il faut que je garde le 'int &size', non?
    ...

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Oui, il faut que tu le gardes.

    Désolé, j'avais mal lu le commentaire (gris sur bleu, pas facile)...
    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.

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Points : 218
    Points
    218
    Par défaut
    Yeah,

    j'ai tenté les vector
    et ça marche du tonnerre!!!


    Merci, merci

  11. #11
    Membre averti Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Points : 417
    Points
    417
    Par défaut
    Citation Envoyé par melleb Voir le message
    Whahou!!
    Merci Rafy pour avoir consacrer un peu de ton temps à ces explications.

    Par contre, je sais pas trop si tu as fait attention
    (où peut être que c'est moi qui ait du mal à comprendre ce que tu a mis)
    mais à l'appel de ma méthode, je ne connais pas le nombre d'éléments que contiendra mon tableau au retour,
    c'est pourquoi je pensais passer en référence la taille...

    dans ce cas, il faut que je garde le 'int &size', non?
    ...
    Ben la variable size est une variable d'entrée ?
    Le role de MaMethode c'est tu lui donne un entier positif, et un tableau, la fonction va mettre dans de tableau autant d'element que passé en argument...
    (ou alors j'ai pas compris le but du truc ...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monTableau = (MaClasse*)malloc(size * sizeof(MaClasse));
    Tu ne la modifie pas... Ou alors je n'ai pas compris le role de la méthode..
    Si tu ne la modifie pas je reste sur mes positions ^^ (passer par valeur)
    Si par contre tu la destines à retourner combien d'octets on été alloué, alors effectivement il ne faut pas la passer par valeur. Et dans ce cas je ferrai en sorte que la fonction retourne cette valeur, plutôt que de la mettre en argument
    Première grosse démo en construction :
    http://bitbucket.org/rafy/exo2/

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Points : 218
    Points
    218
    Par défaut
    Rafy,

    effectivement, le nombre d'éléments est déterminé dans MaMethode...
    il fallait donc bien que je la passe en référence (ou la faire retourner, si tu préfères)

    Mais du coup, avec les vectors, pas besoin
    je passe en référence un vector sans aucun élément,
    dans MaMethode, j'ajoute les éléments avec un push_back
    et ensuite, après l'appel à MaMethode, je peux obtenir le nombre d'élément ajoutés avec un size
    ça le fait!

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

Discussions similaires

  1. Passage par référence versus par pointeur
    Par Seabast888 dans le forum Débuter
    Réponses: 14
    Dernier message: 14/09/2009, 18h17
  2. Réponses: 5
    Dernier message: 21/09/2008, 09h45
  3. Réponses: 8
    Dernier message: 17/09/2008, 12h11
  4. Réponses: 1
    Dernier message: 09/07/2006, 23h39
  5. Références et pointeurs sur un tableau
    Par smag dans le forum C++
    Réponses: 2
    Dernier message: 01/03/2005, 20h29

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