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 :

créer un vector<struct>


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut créer un vector<struct>
    Salut,

    Débutant total en C++, j'aimerais savoir si cette façon de faire un tableau de strucures est correcte. Si oui, j'aurais cru que la méthode at() retournerait une copie de la structure, or elle semble travailler par pointeurs puisque si l'on modifie "le truc" retourné par la méthode at(), on modifie bien l'instance. C'est correct 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
    16
    17
    18
    19
    20
    21
    22
    #include <iostream>
    #include <vector>
     
    typedef struct
    {
        size_t id;
        char* label;
    }DUMMY;
     
    int main()
    {
        std::vector<DUMMY> items;
        items.push_back((DUMMY){7, "item1"});
        items.push_back((DUMMY){5, "item2"});
        items.push_back((DUMMY){12345, "item3"});
        items.at(2).id = 54321; // modif de l'instance ou de la copie
        for(size_t index = 0; index < items.size(); index++)
        {
            std::cout << "id:" << items.at(index).id << " label:\"" << items.at(index).label << "\"\n";
        }
        return 0;
    }

    Encore une question, y a t-il moyen de supprimer le cast (DUMMY) des 3 lignes similaires?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    items.push_back((DUMMY){7, "item1"});
    A+

    Pfeuh

  2. #2
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Salut,

    Alors tout d’abord, les struct ne sont pas très "C++". Surtout si tu es débutant, utilise plutôt des class
    Selon si tu es très grand débutant ou un peu débutant, tu peux aller voir sur la page sur les tuto C++, ou alors dans la faq c++ pour en apprendre un peu plus sur les classes.

    Revenons à ton problème. Je ne détaillerai pas car il y aurait de quoi faire un cour de C++. Je te donne une liste de mot clef, d'idée.
    Lorsque tu crée une classe, tu doit définir un constructeur (faq c++ class, contructeur, etc...). Ce qui remplacera ton cast DUMMY avec la list d'initialisation, très "C like"

    Le at() ne renvois pas une copie, ni un pointeur, mais une référence (faq c++ pour en savoir plus sur les références). En fait, c'est un genre de pointeur en moins "olé olé". C'est à dire que tu ne vas pas jardiner à la main dans la mémoire. Mais oui, tu modifie bien "le truc qu'il y a dans le vecteur".

    Tu peux aussi utiliser l'operator[] à la place du at() (faq c++ operator):
    Voilà. Je sais que c'est assez rapide comme réponse, mais ta question qui peut paraitre anodine fait en fait appel à plein de notion de C++ que je ne peux pas détailler ici.

  3. #3
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par pyros Voir le message
    ta question qui peut paraitre anodine fait en fait appel à plein de notion de C++ que je ne peux pas détailler ici.
    Non, ce n'était pas anodin, ça me permet de mesurer le monde qu'il y a entre le C (d'où je viens) et le C++. Merci pour ta réponse et les pistes qu'elle m'a ouvertes.

    A+

    Pfeuh

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

    D'abord, il faut comprendre le principe de fonctionnement des collections de la STL... :

    L'ajout d'éléments se fait par copie. C'est à dire que, si tu as un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
        std::vector<Dummy> tab;
        Dummy dum;
        dum.id = 15;
        tab.push_back(dum);
        dum.id= 20;
        std::cout << "size for dum : " << dum.id << std::endl
                 << "size for tab[0] : " << tab[0].id << std::endl;
        return 0;
    }
    tu n'obtiendra pas le résultat 20 pour dum et 20 pour tab[0] mais... 20 pour dum et 15 pour tab[0];

    Autrement, une fois que l'élément a été ajouté à ta collection, tu récupérera soit une référence (un alias, ou, comme l'a dit pyros, une "sorte de pointeur" qui garde la syntaxe classique, même si ce n'est pas tout à fait vrai) soit un itérateur, c'est à dire un objet qui te permet de parcourrir la collection (entre autres avec l'operateur d'incrémentation "++" ) et qui utilise la syntaxe des pointeurs.

    Ceci dit, en ce qui concerne le code même de ta structure :

    Tout comme en C, les identifiants entièrement écrits en majuscules sont "classiquement" réservés par convention pour le préprocesseur. Il vaudrait donc mieux utiliser Dummy que ... DUMMY.

    De plus, la définition d'un type utilisateur (qu'il s'agisse d'une énumération, d'une structure ou d'une classe ) provoque la déclaration du type en question.

    Il n'est donc plus nécessaire de passer par le typedef struct, mais on peut se contenter d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Dummy
    {
        size_t id;
        char *label;
    };
    En outre, il faut savoir que C++ fournit, en standard, une classe qui a pour objectif de gérer (de manière totalement transparente pour l'utilisateur) les chaines de caractères.

    Comme je présumes que label est destiné à représenter une telle chaine de caractères, tu aurais largement intérêt à préférer cette classe...

    Ne serait-ce que parce que la gestion des chaines de caractères est très loin d'être simple en C (or, char *, c'est... une chaine "C style"...)

    Enfin, on peut considérer que, si l'on vient à modifier l'id ou le label, on obtient un élément totalement différent.

    Il serait donc "utile" (et des plus intéressants) de rendre ces données privées (de manières à ce que seules l'objet puisse y accéder), et de ne fournir vers "l'extérieur" que... des fonctions permettant d'y accéder en lecture.

    Il faudra alors cependant également prévoir de fournir un constructeur (cf la FAQ )qui aura pour objectif de s'assurer que ton objet est correctement initialisé au moment où tu le crées.

    Au final, Dummy pourrait ressembler à
    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
    /* la seule différence entre une struct et une class en C++ est 
     * l'accessibilité qui y est appliquée :publique pour les struct et privée
     * pour les class
     */
    class Dummy
    {
        public:
            /* le constructeur */
            Dummy(size_t i, std::string const & l):id_(i),label_(l){}
            /* les "accesseurs" qui nous intéressent */
            size_t id() const{return id_;}
            std::string const & label() const{return label_;}
        private:
            /* les données réellement utilisées */
            size_t id_;
            std::string label_;
     
    };
    int main()
    {
        std::vector<Dummy> tab;
        tab.push_back(Dummy(1,"le premier"));
        tab.push_back(Dummy(2,"le deuxieme"));
        tab.push_back(Dummy(3,"le troisieme"));
        tab.push_back(Dummy(4,"le dernier"));
     
    }
    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

  5. #5
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Tout comme en C, les identifiants entièrement écrits en majuscules sont "classiquement" réservés par convention pour le préprocesseur. Il vaudrait donc mieux utiliser Dummy que ... DUMMY.
    C'est noté. Je me suis basé sur la structure FILE qui est en majuscules et qui est la première qui m'est venue à l'esprit.. Merci pour l'exemple de code C++ qui est très parlant et très pédagogique..

    A+

    Pfeuh

  6. #6
    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
    Citation Envoyé par pfeuh Voir le message
    C'est noté. Je me suis basé sur la structure FILE qui est en majuscules et qui est la première qui m'est venue à l'esprit.. Merci pour l'exemple de code C++ qui est très parlant et très pédagogique..

    A+

    Pfeuh
    Si ce n'est que FILE en C est... une définition préprocesseur, permettant de cacher l'intégralité d'une structure sous-jascente... CQFD

    Tu n'as, en effet, aucun moyen de travailler avec FILE autrement que... en passant par les fonctions qui prennent un FILE en paramètre (ou renvoyant un pointeur dessus)
    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

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Enfin, on peut considérer que, si l'on vient à modifier l'id ou le label, on obtient un élément totalement différent.
    Supposition audacieuse.
    Quand ma femme a changé de nom en m'épousant, elle est restée la même personne.

    Citation Envoyé par koala01 Voir le message
    Il serait donc "utile" (et des plus intéressants) de rendre ces données privées (de manières à ce que seules l'objet puisse y accéder), et de ne fournir vers "l'extérieur" que... des fonctions permettant d'y accéder en lecture.
    Non, l'encapsulation n'est pas toujours utile. Et cela rajoute un niveau d'indirection supplémentaire. À faire si nécessaire, sans zèle.

  8. #8
    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
    Par défaut
    Salut,

    Citation Envoyé par oodini Voir le message
    Supposition audacieuse.
    Quand ma femme a changé de nom en m'épousant, elle est restée la même personne.
    Je ne mettrai pas ma tête sur le billot. Ce n'est pas aussi anodin que l'on a tendance à le penser que de changer de nom. Un nom joue dans la représentation de soi mais aussi dans ses rapports aux autres.

    Citation Envoyé par oodini Voir le message
    Non, l'encapsulation n'est pas toujours utile. Et cela rajoute un niveau d'indirection supplémentaire. À faire si nécessaire, sans zèle.
    C'est pas pour contredire, mais c'est à peu près le contraire que j'aurais tendance à préconiser : à ne pas faire si vraiment justifié et sans zèle. Par défaut, capturer le bon concept avec son bon niveau sémantique et mettre en place l'encapsulation me semblent être la démarche première à préconiser. Et ne pas faire d'encapsulation a probablement à voir avec la sémantique faible de l'amalgame des composants (en général, cela traduit l'absence d'invariant à garantir) et est probablement l'exception.

  9. #9
    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
    Citation Envoyé par oodini Voir le message
    Supposition audacieuse.
    Quand ma femme a changé de nom en m'épousant, elle est restée la même personne.
    Attention, elle prend ton nom comme deuxième nom, même si son premier passe du coté de "née" ou du "mauvais coté" du trait d'union...

    Ton nom à toi est "temporaire" pour ta femme et ne durera que le temps du mariage (je ne te souhaites évidemment pas de divorcer, on est bien d'accord ) alors que son nom "de jeune fille" lui restera quoi qu'il puisse arriver

    Non, l'encapsulation n'est pas toujours utile. Et cela rajoute un niveau d'indirection supplémentaire. À faire si nécessaire, sans zèle.
    A l'instar de 3D, je trouve que tu pars dans le mauvais sens ici...

    L'encapsulation doit, par défaut, être appliquée, les cas où elle ne devrait pas l'être n'étant sommes toutes que l'exception

    Je ne parle pas des fonctions setXXX dont je ne suis absolument pas partisan, mais d'une encapsulation correcte grace à laquelle les modifications éventuellement apportées aux données se font au travers de comportements réputés comme ayant de grandes chances de rester valides sans le temps: elle permet réellement d'augmenter le respect de l'OCP
    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

  10. #10
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par oodini Voir le message
    Supposition audacieuse.
    Quand ma femme a changé de nom en m'épousant, elle est restée la même personne.
    Parce que le nom de ta femme ne fait pas partie de ses propriétés intrinsèque

    Non, l'encapsulation n'est pas toujours utile. Et cela rajoute un niveau d'indirection supplémentaire. À faire si nécessaire, sans zèle.
    Vade-retro !

    1/ Une encapsulation bien faite ne rajoute rien.
    2/ Elle est TOUJOURS utile
    3/ ce n'est pas une question de zèle, c'est une question de vie ou de mort du projet
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  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
    Par défaut
    Bonjour,
    Citation Envoyé par pyros Voir le message
    Alors tout d’abord, les struct ne sont pas très "C++". Surtout si tu es débutant, utilise plutôt des class
    Juste une remarque : les struct sont tout autant "C++" que les class. Les deux mots clés sont équivalents pour définir un type à la nuance près d'une visibilité et un héritage par défaut public avec struct et privé avec class. Cf F.A.Q. Quelle est la différence entre class et struct ?

    On utilise même très souvent struct en C++ objet sans états, foncteurs, traits&policies, prog générique...

    Comment choisir l'un plutôt que l'autre. On recommande parfois d'utiliser struct pour les types sans invariants et plutôt class pour les types avec des invariants. Ou une autre façon, les types POD (donc sans invariants) en struct, les autres en class

Discussions similaires

  1. Créer un Vector multi_types
    Par bowow dans le forum C++
    Réponses: 16
    Dernier message: 03/05/2015, 15h52
  2. [Débutant] Créer un tableau de struct
    Par TopCao dans le forum MATLAB
    Réponses: 11
    Dernier message: 17/02/2010, 17h30
  3. Réponses: 12
    Dernier message: 23/03/2006, 14h13
  4. lire fichier et créer vector
    Par belukrin dans le forum MFC
    Réponses: 6
    Dernier message: 18/02/2006, 01h21
  5. mettre un struct dans un vector
    Par Biosox dans le forum SL & STL
    Réponses: 2
    Dernier message: 02/02/2006, 16h34

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