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

Langage C++ Discussion :

Structure dans une Structure : Pointeur ou Objet?


Sujet :

Langage C++

  1. #1
    Membre confirmé Avatar de TNT89
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 615
    Points
    615
    Par défaut Structure dans une Structure : Pointeur ou Objet?
    Bonjour,

    Comme un petit bout de code vaut mieux qu'un long discours :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template< unsigned int Dim, typename T>
    struct VECTOR
    {
            T data[Dim];
    };
    OU
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template< unsigned int Dim, typename T>
    struct VECTOR
    {
            T* data[Dim];
    };
    En fait je ne sais pas quel code adopter entre ces deux possibilités sachant que T peut être un type primitif ou une structure...
    Comment se passe la gestion en mémoire des objets? (leurs composantes sont elles maintenues groupées ou, au contraire, éclatées?)

    Cordialement

  2. #2
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    ne compilera pas.

    en revanche :

    compilera.

    Pour répondre a la question :
    Bas c'est simple ça dépend de la quantité et des opérations a effectuée sur la donnée.
    Si tu as beaucoup de données a allouer par exemple (dès que tu dépasses le mo vois moins) T data[dim] ne suffira pas car c'est alloué sur la pile et ça pétera. Si tu dois faire des agrandissements (vu le nom de la structure ça me parait fort probable) pareil, un tableau statique est pas ce qu'il y'a de plus pratiques.
    En contrepartie :
    impose une allocation dynamique et donc de gérer la mémoire. (ça implique de déclarer ta classe sous la forme canonique orthodoxe de coplien).
    Pour l'alignement mémoire : oui les objets seront alignés en mémoire.

    Enfin si c'est a visé didactique pourquoi pas, sinon autant utilisé la STL et notamment ici std::vector<>
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par Goten Voir le message
    ne compilera pas.
    FAUX...

    [EDIT]Du moins pour autant que dim soit une constante connue à la compilation (mais cette réserve est également valable pour T tab[dim] )
    [/EDIT]

    Par contre, tu n'aura pas forcément ce que tu crois :

    tu obtiendra en fait un tableau contenant dim pointeurs vers une structure de type T contigus en mémoire (les pointeurs étant contigus en mémoire, les objet pointés ayant de grandes chances d'être décéminés )

    Sinon:

    Si tu es sur qu'il ne te faut que maximum dim éléments (qu'il ne t'en faudra jamais dim +1), d'avoir en permancence dim éléments utilisés (ou plus près de dim que de 0 éléments utilisés), et que dim représente un nombre relativement limité (donc, pas surement pas 100 et plus), tu peux effectivement utiliser les deux solutions mais dans des circonstances différentes:

    Tu utilisera la première (T tab[dim]), si tu sais que tu va travailler avec des objets de type T et que tu n'a aucun besoin d'appliquer le polymoprhisme.

    Tu utilisera la seconde ( T* tab[dim]) si tu sais que tu va travailler avec des pointeurs ou si tu estime qu'il est possible que T puisse avoir un comportement polymorphe.

    Cependant, il faudra aussi porter une attention toute particulière à la validité de tes pointeur dans le deuxième cas (il faut être sur que ta structure ne fasse jamais référence à une adresse devenue invalide suite à la destruction de l'objet pointé), ce qui peut arriver très vite.

    Il peut donc être intéressant de travailler non plus avec des pointeurs bruts, mais plutôt avec des pointeurs intelligents (auto_ptr ou autres)

    Enfin, si tu ne sais pas à la base estimer clairement le nombre d'éléments (ou de pointeurs sur éléments de type T) que ta structure devra manipuler, il sera certainement très intéressant d'utiliser les conteneurs de la STL (dont par exemple la classe vector, disponible dans l'espace de noms std par inclusion du fichier d'en-tête <vector>, qui fonctionne exactement comme un tableau "C style" )

    Si tu décide de travailler avec des pointeurs vers des adresses mémoires allouées dynamiquement, boost::ptr_container sera sans doute à préférer de manière à manipuler plus surement tes pointeurs
    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 chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Ouaip autant pour moi, j'ai étais un peu vite en besogne. (on mettra ça sur le compte de la fatigue). Toujours est-il que ce que je voulais dire c'est que même si ça compile, ça fera pas ce à quoi il s'attend...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  5. #5
    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,
    Comme expliqué précédemment, les 2 sémantiques sont différentes. Dans un cas tu as un tableau de dim éléments de type T, dans le second tu as un tableau de dim éléments de type pointeur (sur T). Si ton objet en s'appelant VECTOR veut modéliser un vecteur au sens de std::vector, alors le plus pertinent est le cas suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template< unsigned int Dim, typename T>
    struct VECTOR
    {
            T data[Dim];
    };
    car en général on attend à ce que les éléments soient contigües en mémoire.

    L'avantage de cette solution est qu'elle peut aussi être utilisée pour l'autre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    VECTOR<3,int> tab_entier;
    VECTOR<3,int*> tab_pointeur_entier;
    Enfin, comme l'a précisé Koala, les pointeurs bruts risquent de te poser des problèmes si tu ne les encapsules pas avec des pointeurs intelligents. Et encore dans ce cas, que signifie un tel tableau avec des trous ?

  6. #6
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Bonjour,

    À moins qu'il s'agisse d'un exercice, std::tr1::array fait exactement ce que tu veux.

    Sinon, préfère « Vector » à « VECTOR », le tout majuscule étant en général associé aux macros.
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  7. #7
    Membre confirmé Avatar de TNT89
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 615
    Points
    615
    Par défaut
    Tout d'abord, merci de vos réponses.
    A propos de l'utilisation de std::vector : je n'ai toujours pas compris pourquoi cela est appelé "vector" alors que c'est en fait une liste. En fait j'ai une vision très mathématique de la chose, et donc pour moi un vecteur est de dimension fixé, sinon ça n'est pas un vecteur. Ensuite, oui cela s'approche d'un exercice, exit donc le recours à une bibliothèque tierce.
    Une utilisation par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        template<typename T>
        struct Complex : Vector<2, T>
        {
             //operateurs, etc...
        };
    Et une déclaration d'un vecteur à trois composantes sur le corps complexe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        Vector<3, Complex<double> > mon_vecteur;
    -> 3DArchi, effectivement la première solution permet d'accéder à la deuxième...
    -> koala01, qu'entends-tu par comportement polymorphe?

  8. #8
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Si tu veux faire du polymorphisme dynamique dans ton conteneur.
    Et non vector n'est pas une list, enfin pas une liste chainée en tout cas.

    Pour:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        struct Complex : Vector<2, T>
    Sa a pas vraiment de sens...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  9. #9
    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
    Il est vrai qu'une liste et un vecteur sont deux structures de données qui se ressemblent (tu peux jeter un coup d'oeil à ce tuto si ça t'intéresse). Les différences principales sont :
    1/ Le vecteur t'assure une contiguïté des objets en mémoire ;
    2/ Une liste a un cout d'ajout et de suppression bien moindre qu'un vecteur.
    Si on tient compte de cette dernière remarque, un vector (ou un tableau) est bien un type implémentant les vecteurs mathématiques : la possibilité de modifier la taille du tableau n'étant là que pour se faciliter la vie ponctuellement. Si la structure doit varier régulièrement en nombre d'élément, une liste est effectivement plus appropriée.

    Pour le comportement polymorphe : si ton tableau doit contenir des éléments en même temps d'un type de base et de types héritant de ce type de base et que tu veux que les appels aux méthodes virtuelles se passe bien, en C++ tu ne peux passer que par des pointeurs (ou des références mais pour ton tableau, ça n'a pas de sens) :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    #include <iostream>
     
    class A
    {
       public:
       virtual void do_it()const
       {
          std::cout<<"A::do_it"<<std::endl;
       }
    };
    class B : public A
    {
       public:
       virtual void do_it()const
       {
          std::cout<<"B::do_it"<<std::endl;
       }
    };
     
    template< unsigned int Dim, typename T>
    struct VECTOR
    {
      T data[Dim];
    };
    int main()
    {
       A a;
       B b;
       VECTOR<2,A> vect_1;
       vect_1.data[0]=a;
       vect_1.data[1]=b;
     
       std::cout<<"VECTOR<2,A> -> do_it"<<std::endl;
      for(int index=0;index<2;++index)
      {
         vect_1.data[index].do_it();
      }
     
       VECTOR<2,A const*> vect_2;
       vect_2.data[0]=&a;
       vect_2.data[1]=&b;
       std::cout<<"VECTOR<2,A const *> -> do_it"<<std::endl;
      for(int index=0;index<2;++index)
      {
         vect_2.data[index]->do_it();
      }
     
       return 0;
    }
    Donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    VECTOR<2,A> -> do_it
    A::do_it
    A::do_it
     
    VECTOR<2,A const *> -> do_it
    A::do_it
    B::do_it

  10. #10
    Membre confirmé Avatar de TNT89
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 615
    Points
    615
    Par défaut
    Citation Envoyé par Goten
    Sa a pas vraiment de sens...
    Pourquoi?

    En tout cas je dois privilégier la première écriture mais être prudent dans son utilisation?

  11. #11
    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
    Citation Envoyé par TNT89 Voir le message
    En tout cas je dois privilégier la première écriture
    J'aurais tendance à dire oui.

    Citation Envoyé par TNT89 Voir le message
    mais être prudent dans son utilisation?
    Il ne s'agit pas vraiment de prudence. Car la même remarque s'applique aux conteneurs standards (std::vector par exemple). Si tu veux utiliser les éléments avec leur type de base, alors il faut stocker les éléments par adresses (VECTOR<2,A const *>) et non par valeurs (VECTOR<2,A>).
    On voit ainsi que la première écriture te permet de choisir au niveau de la variable et ne l'impose pas au niveau de la structure.

  12. #12
    Membre confirmé Avatar de TNT89
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 615
    Points
    615
    Par défaut
    Merci pour votre aide!

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

Discussions similaires

  1. Afficher les valeurs d'une structure dans une matrice
    Par yabbiyou dans le forum MATLAB
    Réponses: 1
    Dernier message: 22/02/2007, 12h26
  2. Passage d'une structure dans une fonction
    Par god_enel dans le forum C
    Réponses: 7
    Dernier message: 01/02/2007, 15h33
  3. Passage d'une structure dans une fonction
    Par god_enel dans le forum C
    Réponses: 8
    Dernier message: 22/01/2007, 15h35
  4. Passer une structure dans une fonction ...
    Par pilouface dans le forum C
    Réponses: 4
    Dernier message: 03/04/2006, 01h00
  5. [MFC] Passage d'une structure dans une method
    Par KPitN dans le forum MFC
    Réponses: 5
    Dernier message: 18/06/2004, 10h11

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