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 :

GLfloat dynamique et pointeur


Sujet :

C++

  1. #21
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Oui mais c'est quand meme pas évident, bon donc dans mon cas pas de pointeurs mais c'est tout à fait possible aussi ? et convertir mon pointeur en tableau de float ?

    Donc si j'essaie de comprendre est ce ma classe est bonne la même si il le fait implicitement si je le mentionne pas; est ce que la syntaxe est bonne ?
    & accolé a const ou pas :

    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
     
    class Vertices
    {
    public:
      //Vertices (GLfloat def_x, GLfloat def_y, GLfloat def_z) : x(def_x), y(def_y), z(def_z) {}
      Vertices (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}
     
        // some data (i.e. x and y)...
      GLfloat x, y, z;
    };
     
           vector<Vertices> arMyClass;
     
         arMyClass.push_back(Vertices(0.0f, 0.0f,1.0f));
         arMyClass.push_back(Vertices(1.0f, 0.0f,0.0f));

  2. #22
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Oui c'est bon. (presque : le nom est mal choisit ; vertices = ensemble de vertex ; ta classe représente un vertex et non des vertices)

    Si tu connais la taille, tu peux allouer directement un tableau contenant le nombre de de vertex nécessaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<Vertices> arMyClass(Nb_Vertices); // ou avec resize()
    Si tu connais pas le nombre exacte mais que tu as une idée de l'ordre de grandeur (100, 1000, 100000 des vertices...), tu peux réserver une taille pour éviter les réallocations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    vector<Vertices> arMyClass;
    arMyClass.resize(Nb_Vertices_Probable);

    Pour comprendre la différence entre un tableau de GLfloat (ou de Vertex) et un tableau de pointeurs de Vertex (Vertex*) d'un point de vue de la mémoire, je t'ai fait un petit schéma.
    Images attachées Images attachées  

  3. #23
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Si tu connais la taille, tu peux allouer directement un tableau contenant le nombre de de vertex nécessaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<Vertices> arMyClass(Nb_Vertices); // ou avec resize()
    Ou Boost.Array, bien que je n'en ai toujours pas compris l'intérêt par rapport à un vector...

  4. #24
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Donc d'où l'utilité d'un non pointé pour l'utilisation de la méthode VBO :

    glBufferData(target, v.size() *3* sizeof( GLfloat ), NULL, mode);

    Block de memoire contigüe c'est ca ?

    Par contre au niveau syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertices (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}
    C'est pareil que ? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertices (GLfloat const & def_x, GLfloat const & def_y, GLfloat const & def_z) : x(def_x), y(def_y), z(def_z) {}
    Autre chose si j'avais utilisé ton constructeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertices(Vertices const& o) : x(o.x), y(o.y), z(o.z) {}
    Comment ensuite je l'aurais appelé ?

    et en utilisant const je pourrais modifier les valeurs ensuite ?

    Si je veux modifier l'indice 0 ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    arMyClass.push_back(Vertices(0.0f, 0.0f,1.0f)); // ajoute
    // et si je veux enlever ou modifer l'indice 0 ?

  5. #25
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par oodini Voir le message
    Ou Boost.Array, bien que je n'en ai toujours pas compris l'intérêt par rapport à un vector...
    Boost array est un tableau de taille statique (donc similaire à T t[N];) fournissant une interface similaire à std::vector (pour être utilisé par les algorithmes de la STL)

  6. #26
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Oui, mais je ne vois pas quelle est la plus-value par rapport à un vecteur dont on aurait initialement fixé la taille.

  7. #27
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    std::vector alloue des données supplémentaire pour fonctionner (size, pointeur vers le premier élément)
    Je suppose qu'il y a aussi plus de tests interne dans std::vector du fait que c'est dynamique.
    Mais il va falloir attendre un peu les spécialistes de boost pour les précisions/corrections.

  8. #28
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Et concernant mes dernières questions, peut-on me répondre ou cela mérite pas de réponses

  9. #29
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Citation Envoyé par regsregs Voir le message
    Donc d'où l'utilité d'un non pointé pour l'utilisation de la méthode VBO :

    glBufferData(target, v.size() *3* sizeof( GLfloat ), NULL, mode);

    Block de memoire contigüe c'est ca ?
    j'ai pas compris la question.

    Citation Envoyé par regsregs Voir le message
    Par contre au niveau syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertices (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}
    C'est pareil que ? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertices (GLfloat const & def_x, GLfloat const & def_y, GLfloat const & def_z) : x(def_x), y(def_y), z(def_z) {}
    Si la seule différence est l'espace entre const et &, oui c'est identique. Les espaces ici ne sont pas significatifs.

    Citation Envoyé par regsregs Voir le message
    Autre chose si j'avais utilisé ton constructeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertices(Vertices const& o) : x(o.x), y(o.y), z(o.z) {}
    Comment ensuite je l'aurais appelé ?
    Le constructeur par copie automatiquement lorsqu'une copie de l'objet est nécessaire (passage d'un paramètre par valeur) ou lorsque tu définis une variable à partir d'une autre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Verctices a;
    Vertices b(a); // appelle le constructeur par copie
     
    void fonction(Vertices par);
     
    fonction(a); //appelle le constructeur par copie
    Dans ta classe, je ne pense pas que tu doives définir le constructeur par copie et l'opérateur d'assignation. Par défaut, le compilateur en donne un qui fait une copie des attributs ce que le tien se contente de faire. Donc autant laisser le compilateur le faire sans oubli (cf F.A.Q. )

    Citation Envoyé par regsregs Voir le message
    et en utilisant const je pourrais modifier les valeurs ensuite ?

    Si je veux modifier l'indice 0 ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    arMyClass.push_back(Vertices(0.0f, 0.0f,1.0f)); // ajoute
    // et si je veux enlever ou modifer l'indice 0 ?
    const s'applique uniquement au paramètre lors de l'appel du constructeur. Cette constance n'est valable que dans la fonction exécutée. Ensuite ton objet peut être modifié à loisir.


    @Boost.Array : (comme std::array) cherche à encapsuler les tableaux T[N] là où std::vector encapsule les tableaux dynamiques new T[N]. Donc, une différence majeure avec un std::vector (outre qu'on ne peut changer la taille) est que les données sont construites sur la pile et non sur le tas ne nécessitant donc pas d'allocateur.

  10. #30
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Citation Envoyé par gbdivers
    Tu peux également ajouter dans ta classe StructureObjet le constructeur par copie, l'opérateur d'affectation = et les opérateurs d'égalité et de différence (== et !=)
    La copie et l'affectation devrait être générée automatiquement et de façon approprié par le compilateur pour une classe comme celle-ci. Nul besoin de les redéfinir. (cf F.A.Q.)
    En fait, je vais être encore plus critique sur ce que j'ai dit : il ne faut surtout pas avoir besoin de redéfinir le constructeur par copie ou l'opérateur d'affectation.

    Pour que le tableau de Vertex vector<Vertex> soit un tableau de GLfloat, il faut absoluement que la classe Vertex ne contiennent que les GLfloat. Donc pas de pointeur ou d'autres structures. Donc si on a besoin de redéfinir le constructeur par copie, c'est qu'il y a un problème.

    Donc il faut oublier ce que j'ai dit : pas de redéfinition du constructeur par copie (sauf traitement spécifique fait dans le constructeur mais je vois pas quoi à priori)

    Donc d'où l'utilité d'un non pointé pour l'utilisation de la méthode VBO :

    glBufferData(target, v.size() *3* sizeof( GLfloat ), NULL, mode);

    Block de memoire contigüe c'est ca ?
    Oui, les buffers copy prennent l'adresse d'un bloc mémoire et la taille du bloc mémoire et le copie en une seule fois dans la mémoire gpu. Donc il faut que les données forment un seul bloc en mémoire (données contiguës).

    Par contre, petit détail, ton code ne copie pas les données vers le gpu. Il faut également donner le pointeur vers tes données (ou appeler la copie explicitement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glBufferData(target,  v.size() *3* sizeof( GLfloat ), &VertexArray[0], mode);

  11. #31
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Il me reste quand même des interrogations, quand vous dites pas besoin de redéfinir le constructeur par copie, là il y'a bien un constructeur de copie là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Vertices
    {
    public:
         Vertices (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {} // constructeur de copie
           GLfloat x, y, z;
    };
    Si j'en met pas ? comment envoyer mes valeurs ? Je sens que je dis des bétises

    Et pour le VBO, en fait je fais ensuite un glBufferSubData, c'est pas utile ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
             void  monObjet::initVBO(Vertex& v)
         {
             glGenBuffers(1,&bufVertex);
             glBindBuffer(target, bufVertex);
             glBufferData(target,  v.size()*3 * sizeof( GLfloat ), NULL, mode);
             glBufferSubData(target, 0,  v.size()*3*sizeof( GLfloat ),  v);
        }

  12. #32
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par regsregs Voir le message
    Il me reste quand même des interrogations, quand vous dites pas besoin de redéfinir le constructeur par copie, là il y'a bien un constructeur de copie là :
    Relis le post de 3DArchi

    Et pour le VBO, en fait je fais ensuite un glBufferSubData, c'est pas utile ?
    Regarde mon code et lit la doc de glBufferData

  13. #33
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Le constructeur par copie automatiquement lorsqu'une copie de l'objet est nécessaire (passage d'un paramètre par valeur) ou lorsque tu définis une variable à partir d'une autre:

    Verctices a;
    Vertices b(a); // appelle le constructeur par copie

    void fonction(Vertices par);

    fonction(a); //appelle le constructeur par copie Dans ta classe,

    je ne pense pas que tu doives définir le constructeur par copie et l'opérateur d'assignation. Par défaut, le compilateur en donne un qui fait une copie des attributs ce que le tien se contente de faire. Donc autant laisser le compilateur le faire sans oubli
    Désolé j'ai pas compris

  14. #34
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Bon j'insiste lourdement mais si je comprends pas la base, ce n'est même pas la peine de continuer...

    Donc en résumé, une classe vide :

    possède un constructeur par defaut, un constructeur de copie, un destructeur, un opérateur d'affectation.

    Dans mon cas je veux un conteneur de GLfloat.

    si j'utilise ma classe vertex pour stocker mes sommets j'avais cette classe qui fonctionne bien mais qui utilise mon constructeur de copie:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class Vertex{
         Vertex (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}
     
     
      GLfloat x, y, z;
    };
     
    //que j'appelle ainsi :
    vector<Vertex> arMyClass;
    arMyClass.push_back(Vertex(1.0f, 0.0f,0.0f));
    Maintenant si je n'utilise pas de constructeur de copie, je dois quand même utiliser un constrcuteur avec 3 arguments pour stocker mes GLfloat ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Vertex{
        Vertex (GLfloat def_x, GLfloat def_y, GLfloat def_z) : x(def_x), y(def_y), z(def_z) {}     
     
      GLfloat x, y, z;
    };
     
    //que j'appelle ainsi :
    vector<Vertex> arMyClass;
    arMyClass.push_back(Vertex(1.0f, 0.0f,0.0f));
    Mais si je ne fais que stocker des GlFloat ne vaut t'il pas défininir un vecteur de Glfloat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     vector<GLfloat> vertex;
     
    vertex.push_back(-1.0);
    Voilà ma problématique du moment

  15. #35
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    si j'utilise ma classe vertex pour stocker mes sommets j'avais cette classe qui fonctionne bien mais qui utilise mon constructeur de copie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vertex (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}
    J'ai l'impression que tu penses que ton constructeur avec const est un constructeur par copie et le suivant, sans const, est un constructeur... pas par copie ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vertex (GLfloat def_x, GLfloat def_y, GLfloat def_z) : x(def_x), y(def_y), z(def_z) {}
    Donc j'insite lourdement, relis le post de 3DArchi et regarde le lien qu'il a donné vers la FAQ pour connaitre la syntaxe d'un constructeur par copie. Aucun des 2 constructeurs que tu donnes est un constructeur par copie. Et relis aussi le post de 3DArchi pour comprendre ce qui se passe et pourquoi tu n'as pas besoin de définir ton constructeur par copie.

    Mais si je ne fais que stocker des GlFloat ne vaut t'il pas défininir un vecteur de Glfloat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    vector<GLfloat> vertex;
    vertex.push_back(-1.0);
    C'est possible (mais même en C on créé une structure en général). Mais tu perds les avantages de l'orienté objet.

  16. #36
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Oui en effet le & je pensais que c'etait une copie par réference et l'autre non.

    C'est pas cela ?

  17. #37
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,

    Qu'est-ce qu'un constructeur ?



    Qu'est-ce qu'un constructeur par défaut ?


    Qu'est-ce qu'un constructeur de copie ?

    Vertex (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}, et Vertex (GLfloat def_x, GLfloat def_y, GLfloat def_z) : x(def_x), y(def_y), z(def_z) {} ne sont pas des constructeurs de copie.

  18. #38
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Ok je pense avoir compris le constructeur de copie, le constructeur de copie va donc me copier l'objet à partir d'un autre objet de ma classe, c'est à dire copie chacun de ces attributs pour les associés à ses propres attributs.

    Ensuite L'opérateur d'affectation par defaut donc non mentionné dans ma classe va copier la valeur d'un objet dans un autre.

    Par contre concernant mon constructeur par paramètres, qui n'est pas un constructeur de copie on est d'accord pas besoin là car le compilateur va le rajouter, mais ces 2 constructeurs sont identiques ? l'un avec const& permet de ne pas le modifier les valeurs dans la fonction et l'autre pas car je n'ai pas const&, mais je pourrais aussi ecrire const sans le & est ce pareil que const :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertex (GLfloat const& def_x, GLfloat const& def_y, GLfloat const& def_z) : x(def_x), y(def_y), z(def_z) {}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Vertex (GLfloat const def_x, GLfloat const def_y, GLfloat const def_z) : x(def_x), y(def_y), z(def_z) {}
    Juste ou suis encore à l'ouest

  19. #39
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Tu as trois façons de passer les paramètres:
    • par valeur : void fonction(TYPE argument);Lors de l'appel de la fonction :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      TYPE variable = TYPE();
      fonction(variable);
      , la valeur de variable est copiée dans le paramètre de la fonction argument. La fonction est donc exécutée avec sa propre copie du paramètre, elle peut le modifier à loisir et cela ne changera pas le paramètre de l'appelant :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
       
      void fonction(TYPE argument)
      {
         argument = QUELQUE_CHOSE;
      }
       
      int main()
      {
      TYPE variable = AUTRE_CHOSE;
      fonction(variable);
      // ici variable==AUTRE_CHOSE;
      }
    • par référence : void fonction(TYPE & argument);. Lors de l'appel de la fonction :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      TYPE variable = TYPE();
      fonction(variable);
      , le paramètre de la fonction argument est un synonyme du paramètre de l'appel variable. La fonction appelée et l'appelante partagent donc la même variable. Par conséquent, si la fonction change la valeur du paramètre, la modification se retrouve une fois revenu chez l'appelant :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
       
      void fonction(TYPE &argument)
      {
         argument = QUELQUE_CHOSE;
      }
       
      int main()
      {
      TYPE variable = AUTRE_CHOSE;
      fonction(variable);
      // ici variable==QUELQUE_CHOSE;
      }
    • par pointeur : void fonction(TYPE * argument);Lors de l'appel de la fonction :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      TYPE variable = TYPE();
      fonction(&variable);
      , l'adresse du paramètre de l'appel variable (c'est à dire l'emplacement mémoire où se trouve cette variable) est copiée dans le paramètre pointeur de la fonction argument. La fonction appelée écrit donc dans le même emplacement mémoire que la variable de l'appelante. Par conséquent, si la fonction change la valeur du paramètre, la modification se retrouve une fois revenu chez l'appelant :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
       
      void fonction(TYPE *argument)
      {
         *argument = QUELQUE_CHOSE;
      }
       
      int main()
      {
      TYPE variable = AUTRE_CHOSE;
      fonction(&variable);
      // ici variable==QUELQUE_CHOSE;
      }


    Se pose la question de quand privilégier tel ou tel type d'appel :

    • Quand passer des paramètres par valeur ?
      On passe des paramètres par valeur quand on ne souhaite pas que la variable de l'appelant soit impactée par les modification de l'argument dans le déroulement de la fonction appelée.
    • Quand passer des paramètres par références
      On passe des paramètres par références quand on souhaite récupérer dans la variable de l'appelant les modifications de l'argument dans le déroulement de la fonction appelée.
    • Quand passer des paramètres par pointeur ?
      Le passage par pointeur ressemble au passage par référence puisqu'on récupère ainsi les modifications mais alors qu'une référence est toujours liée à une variable de l'appelant, un pointeur peut être invalide par exemple en passant le pointeur particulier NULL. Ce qui fait qu'on privilégie un passage par pointeur au détriment d'un passage par référence si et seulement si le cas du pointeur NULL est pertinent, i.e. le paramètre est optionnel.

    Bon et const dans tout ça ? const dit à la fonction ce qu'elle peut faire de l'argument quelque soit le mode de passage :

    void fonction(TYPE argument); : la fonction peut à l'intérieur modifier l'argument même si cette modification est perdu pour l'appelant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void fonction(TYPE argument)
    {
       argument = QUELQUE_CHOSE; // OK
    }
    void fonction(TYPE const argument); : la fonction ne peut pas modifier l'argument même si cette modification serait perdu pour l'appelant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void fonction(TYPE const argument)
    {
       argument = QUELQUE_CHOSE; // ERREUR
    }
    void fonction(TYPE &argument); : la fonction peut à l'intérieur modifier l'argument et cette modification est vu par l'appelant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void fonction(TYPE &argument)
    {
       argument = QUELQUE_CHOSE; // OK - La variable de l'appelant est aussi modifiée
    }
    void fonction(TYPE const & argument); : la fonction ne peut pas modifier l'argument, l'appelant sait donc que sa variable ne sera pas modifiée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void fonction(TYPE const &argument)
    {
       argument = QUELQUE_CHOSE; // ERREUR
    }
    Pour le passage par pointeur, c'est similaire au passage par référence.

    Bon quand mettre const ?
    Dans un passage par valeur, void fonction(TYPE const argument), cela a peu d'intérêt, puisque la fonction se déroule avec son propre jeu d'argument sans modifier ceux des appelants. C'est rarement utilisé et certains compilateurs sortent même un avertissement en demandant s'il ne s'agit pas d'une étourderie...

    Dans un passage par référence (ou pointeur), void fonction(TYPE const &argument), pour indiquer que la fonction ne modifie pas les valeurs des arguments. L'appelant n'a pas besoin de mettre en place une stratégie pour éviter que la fonction modifie ses arguments, puisque le passage par référence constante lui garantie que ces paramètres auront la même valeur avant et après l'appel de la fonction.

    Passage par valeur et passage par référence constante garantissent à l'appelant que ses paramètres ne sont pas modifiés. Mais quand utiliser un passage par référence constante et quand utiliser un passage par valeur ?

    L'objet est une instance d'une classe non copiable, c'est à dire pour laquelle on a interdit le constructeur par copie et l'opérateur d'affectation. Si on ne peut pas faire de copie, il n'y a pas le choix, l'appel doit se faire par référence. Pour signaler la non modification, il faut bien utiliser const et rassurer l'appelant.

    La copie de l'objet est couteuse. L'objet est trop gros et/ou la copie prend trop de temps. On utilise un passage par référence constante pour éviter de payer le coût de la copie mais garantir qu'il n'y aura pas de modification.

    Si on considère que le coût de la copie est négligeable au regard de ce que fait la fonction, on peut utiliser un passage par valeur.

    Le passage par référence a lui aussi un coût lié à l'implémentation et il s'avère que ce coût est souvent supérieur ou égal au passage par copie pour les types natifs : entiers, booléen, réels. Ce sont donc des types pour lesquels on privilégie le passage par valeur plutôt que par référence constante.

  20. #40
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 27
    Points : 6
    Points
    6
    Par défaut
    Merci de ces explications

    Je commence à comprendre, je vais lire cela à tête reposée et faire quelques tests mais j'y vois plus clair

Discussions similaires

  1. Réponses: 6
    Dernier message: 23/05/2011, 19h41
  2. Créer un tableau dynamique de pointeur
    Par Staithes dans le forum Débuter
    Réponses: 4
    Dernier message: 02/12/2010, 07h20
  3. Double tableau dynamique de pointeurs de struct
    Par dedibox26 dans le forum Débuter
    Réponses: 2
    Dernier message: 27/04/2010, 15h24
  4. allocation dynamique et pointeur
    Par siempre dans le forum C
    Réponses: 3
    Dernier message: 29/11/2009, 21h35
  5. Tableau dynamique de pointeurs sur const char*
    Par Le Mérovingien dans le forum Débuter
    Réponses: 6
    Dernier message: 05/06/2008, 14h23

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