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 :

Remplissage d'un vector<> dans une boucle for


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Points : 52
    Points
    52
    Par défaut Remplissage d'un vector<> dans une boucle for
    Bonjour,

    J'aimerais remplir un "vector" de pointeurs d'objets. La taille du vector dépend d'une macro, donc j'aimerais savoir comment je peux remplir le vecteur dans une boucle for intelligemment.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    #define MAX_OBJ   10
     
    vector<Obj*> v;
     
    v.reserve(MAX_OBJ);
     
    for(int i=0; i<MAX_OBJ;i++)
    {
           v[i] = ???;
    }
    Si je remplace les ??? par v[i] = new Obj() j'ai bien sûr une erreur. Je ne peux pas non plus faire "Obj *ob = new Obj(); v[i] = ob" sinon je donne le même pointeur dans toutes mes "cases" ...

    Une idée ?

  2. #2
    Membre éprouvé
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Points : 1 220
    Points
    1 220
    Par défaut
    Bonjour.
    Citation Envoyé par syl1405 Voir le message
    Si je remplace les ??? par v[i] = new Obj() j'ai bien sûr une erreur. Je ne peux pas non plus faire "Obj *ob = new Obj(); v[i] = ob" sinon je donne le même pointeur dans toutes mes "cases" ...

    Une idée ?
    Attention ! Reservation de la mémoire ne signifie pas allocation: la place mémoire est réservée, mais il n'y a pas encore d'éléments à cet endroit.

    Vector te fournit la méthode push_back() pour ajouter des éléments :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #define MAX_OBJ   10
     
    vector<Obj*> v;
     
    v.reserve(MAX_OBJ);
     
    for(int i=0; i<MAX_OBJ;i++)
    {
           push_back(new Obj());
    }
    ceci devrait marcher.

    Bonne chance
    Méphistophélès
    Si la solution ne résout pas votre problème, changez le problème...
    Cours et tutoriels C++ - FAQ C++ - Forum C++.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Points : 52
    Points
    52
    Par défaut
    Citation Envoyé par méphistopheles Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #define MAX_OBJ   10
     
    vector<Obj*> v;
     
    v.reserve(MAX_OBJ);
     
    for(int i=0; i<MAX_OBJ;i++)
    {
           push_back(new Obj());
    }
    ceci devrait marcher.
    Oui super, ça ça marche parfaitement Merci beaucoup pour la réponse !

  4. #4
    Nouveau Candidat au Club
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2010
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Tu peux aussi initialiser la taille dès la création de ton vector:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<Obj*> vec(MAX_OBJ);
    for (unsigned int i = 0; i < vec.size(); ++i) 
      vec[i] = new Obj;

  5. #5
    Membre éprouvé
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Points : 1 220
    Points
    1 220
    Par défaut
    Citation Envoyé par Tesseract Voir le message
    Tu peux aussi initialiser la taille dès la création de ton vector:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<Obj*> vec(MAX_OBJ);
    for (unsigned int i = 0; i < vec.size(); ++i) 
      vec[i] = new Obj;
    C'est moins propre: en effet, on fait Max_OBJ initialisation d'objets en plus(et pour rien). par contre, on peut se contenter de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Obj*> vec(MAX_OBJ);
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Obj*> vec(MAX_OBJ,Obj());//Version plus explicite
    ce qui revient au mème (c'est le constructeur par défaut qui est appelé.)
    Et on aura le même résultat en une ligne.
    Méphistophélès
    Si la solution ne résout pas votre problème, changez le problème...
    Cours et tutoriels C++ - FAQ C++ - Forum C++.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Points : 52
    Points
    52
    Par défaut
    Citation Envoyé par méphistopheles Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Obj*> vec(MAX_OBJ,Obj());
    Ca ça me plait beaucoup, merci Méphistophéles !!

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Points : 52
    Points
    52
    Par défaut
    EDIT: Je fais face à un autre problème ... en réalité, le vecteur que j'initialise est dans une classe, et il doit être commun à toutes les classes filles et de manière static. J'ai donc essayé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class Cla {
    protected:
         static std::vector <Obj*> vec(MAX_OBJ,Obj());         
    }
    Ceci ne fonctionne pas (expected identifier before numeric constant). Après quelques recherches sur le forum, j'ai lu qu'on ne pouvait pas l'initialiser ici le vecteur. Je l'ai donc fait dans le .cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vector <CEP*> Cla::vec(MAX_Obj);
    Là j'ai des erreurs "no matching function for call ..."

    En résumé : comment initialiser un vecteur dont toutes les classes filles héritent et de manière static ?

    Je n'ai plus d'idées !

    Merci pour vos réponses !

  8. #8
    Membre éprouvé
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Points : 1 220
    Points
    1 220
    Par défaut
    Citation Envoyé par syl1405 Voir le message
    En résumé : comment initialiser un vecteur dont toutes les classes filles héritent et de manière static ?

    Je n'ai plus d'idées !

    Merci pour vos réponses !
    Heu... tou d'abors tu déclare un std::vector <Obj*> puis tu essaye d'instancier (dans ton cpp je suppose) un vector <CEP*> :Je n'ai malheuresement ni le code ni l'erreur (puisque -tu ne les a pas fournies), mais les différentes sources d'erreur qui me viennent à l'esprit sont :
    1. CEP n'est pas le même type que Obj
    2. L'un de ces deux paramètre est template
    3. tu utilise un vector alors que tu n'a pas mis using namespace std;
    4. Tu déclare toujours ta variable statique "static std::vector <Obj*> vec(MAX_OBJ,Obj()); " et non "static std::vector <Obj*> vec; "
    "

    Pour d'autre idées, il faudra fournir plus de précisions.

    Bonne chance
    Méphistophélès
    Si la solution ne résout pas votre problème, changez le problème...
    Cours et tutoriels C++ - FAQ C++ - Forum C++.

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Si dans ta classe (dans le .h) tu déclares
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static std::vector <Obj*> vec;
    Et dans ton .cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector <Obj*> Cla::vec(MAX_OBJ);
    Ca va rouler.
    Il te restera juste à instancier des Obj pour remplir ton tableau de pointeurs.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Points : 52
    Points
    52
    Par défaut
    Oh pardon !! J'ai fais un copier-coller de mon code, mais j'ai oublié d'ajuster certains noms de paramètres ...

    De plus, mon erreur provenait d'une erreur de nom (une minuscule au lieu d'une majuscule) ... donc le problème est résolu, le code fonctionnait donc bien.

    Merci encore pour vos réponses !

  11. #11
    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 méphistopheles Voir le message
    C'est moins propre: en effet, on fait Max_OBJ initialisation d'objets en plus(et pour rien). par contre, on peut se contenter de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Obj*> vec(MAX_OBJ);
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Obj*> vec(MAX_OBJ,Obj());//Version plus explicite
    Malheureux, surement pas...

    vec est un vecteur de... pointeurs sur Obj...

    Les pointeurs doivent être:
    • Soit initialisés à NULL (comportement par défaut)
    • soit initialisés avec l'adresse d'objets existants par ailleurs (faites gaffe à la durée de vie de ces objets )
    • soit initialisés avec l'adresse d'objets... créé dynamiquement pour l'occasion
    Toute autre solution mènera à des problème sans noms (n'oubliez pas de les détruire correctement "en temps utiles" )
    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

  12. #12
    Membre éprouvé
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Points : 1 220
    Points
    1 220
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,Malheureux, surement pas...

    vec est un vecteur de... pointeurs sur Obj...

    Les pointeurs doivent être:
    • Soit initialisés à NULL (comportement par défaut)
    • soit initialisés avec l'adresse d'objets existants par ailleurs (faites gaffe à la durée de vie de ces objets )
    • soit initialisés avec l'adresse d'objets... créé dynamiquement pour l'occasion
    Toute autre solution mènera à des problème sans noms (n'oubliez pas de les détruire correctement "en temps utiles" )
    Oups, les pointeurs sont soudainement devenu des objets dans ma tête ><' . C'est effectivement n'importe-quoi.

    Dans ce cas, la méthode avec Reserve est beaucoup mieux. (heureusement que koala repasse pour corriger )
    Méphistophélès
    Si la solution ne résout pas votre problème, changez le problème...
    Cours et tutoriels C++ - FAQ C++ - Forum C++.

  13. #13
    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
    Maintenant, tout comme il est possible de créer un foncteur qui s'occupe de libérer la mémoire d'un pointeur pour travailler avec for_each sous la forme de
    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
    struct Deleter
    {
        void operator()(Obj * o)
        {
            delete o;
        }
    };
    #include <algorithm> 
    int main()
    {
        std::vector<Obj *> tab;
        /* utilisation diverse */
        /*...*/
        /*nettoyage final */
        std::for_each(tab.begin(),tab.end(),Deleter());
        return 0;
    }
    nous pourrions envisager un foncteur "Creator" qui affecterait l'adresse d'un élément nouvellement créé à un pointeur, et partir sur la création d'un vecteur de taille définie:
    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
    class Creator
    {
        void operator()(Obj* o)
        {
            o = new Obj;
        }
    };
    int main()
    {
        std::vector<Obj *> tab(MAX_OBJ);
        std::for_each(tab.begin(),tab.end(),Creator());
        /*...*/
        /* récupéré de plus haut */
        std::for_each(tab.begin(),tab.end(),Deleter());
        return 0;
    }
    Ceci dit, j'ai du mal à comprendre pourquoi une classe de base devrait disposer d'une collection de pointeurs partagée par l'ensemble des instances des classes dérivées.

    Dans quelle mesure ne serait il pas opportun de sortir ce tableau de pointeur de la classe de base pour le placer dans une structure ou une classe que nous veillerions à garder unique et à y faire référence en toute circonstances

    La création d'un singleton dont nous pourrions limiter la diffusion (en le définissant, par exemple, dans le fichier d'implémentation de la classe de base, à laquelle nous ajouterions une fonction protégée qui permet de le récupérer) semblerait être une idée bien plus judicieuse:
    Base.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class ObjectVector;
    class Base
    {
        public:
            /*...*/
        protected :
            ObjectVector /* const */ & getVector() /* const */;
    };
    Base.cpp
    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
    #include <obj.h>
    #include <base.h>
    #include <algorithm>
    class ObjectVector
    {
        public:
            static instance&()
            {
                if(! inst_)
                    inst_=new ObjectVector;
                return * inst_;
            }
            /* permettons d'accéder au vecteur avec les opérateurs * et -> */
            std::vector<Obj*> & operator*(){return inst_->tab;}
            std::vector<Obj*> & operator->(){return inst_->tab;}
        private:
            ObjectVector():tab(MAX_ONJ)
            {
                /* je reprend l'idée précédente :D */
                std::for_each(tab.begin(),tab.end(),Creator());
            }
            ~ObjectVector ()
            {
                std::for_eah(tab.begin(),tab.end(),Deleter());
            }
            static ObjectVector * inst_;
            std::vector<Obj*> tab;
    };
    ObjectVector * ObejctVector::inst_= NULL;
     
    ObjectVector /* const */ & Base::getVector() /* const */
    {
        return ObjectVector::instance();
    }
    Derivee.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <Base.h>
     
    class Derivee : public Base
    {
        public:
            void foo();
    };
    Derivee.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <Derivee.h>
    #include <obj.h>
     
    void Derivee::foo()
    {
        for(int i=0;i<MAX_OBJ;++i)
            *(getVector)[1]->machinChose();
    }
    (Code écrit "à la volée en étant à peine réveillé )

    [EDIT]Si, comme je m'y attends, on se rend compte à l'usage que ce singleton doit être disponible de manière plus générale pour autre chose que les classes dérivées, il "suffira" de créer une unité de compilation (fichiers *.h et *.cpp) qui lui sera dédiée
    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

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Points : 52
    Points
    52
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ceci dit, j'ai du mal à comprendre pourquoi une classe de base devrait disposer d'une collection de pointeurs partagée par l'ensemble des instances des classes dérivées.
    Concrètement, je voulais créer une classe contenant le vecteur, et parmis les deux classes filles créées, l'une peut écrire dedans pour le mettre à jour, et l'autre ne peut que le lire.

    Citation Envoyé par koala01 Voir le message
    Dans quelle mesure ne serait il pas opportun de sortir ce tableau de pointeur de la classe de base pour le placer dans une structure ou une classe que nous veillerions à garder unique et à y faire référence en toute circonstances

    La création d'un singleton dont nous pourrions limiter la diffusion (en le définissant, par exemple, dans le fichier d'implémentation de la classe de base, à laquelle nous ajouterions une fonction protégée qui permet de le récupérer) semblerait être une idée bien plus judicieuse:
    Je n'ai pas beaucoup d'expérience en C++ (pour ne pas dire quasi aucune), je ne connais pas trop les "bons moyens de procéder". J'ai essayé de me débrouiller comme je le pouvais. Je vous remercie donc pour ces informations complémentaires ! Je cherche avant tout à faire un code lisible et le plus propre possible, je vous fais entièrement confiance si cette solution est plus adaptée !

    Je vous remercie beaucoup de me l'avoir exposée !

Discussions similaires

  1. Remplissage d'une structure dans une boucle for
    Par Lorddolf dans le forum MATLAB
    Réponses: 4
    Dernier message: 07/04/2011, 16h52
  2. Shell - Erreur dans une boucle for
    Par claralavraie dans le forum Linux
    Réponses: 4
    Dernier message: 11/01/2006, 13h45
  3. Problème avec une DLL dans une boucle For
    Par BraDim dans le forum Langage
    Réponses: 5
    Dernier message: 20/09/2005, 12h22
  4. [batch] incrémentation dans une boucle for
    Par bart64 dans le forum Scripts/Batch
    Réponses: 4
    Dernier message: 08/09/2004, 20h05
  5. Réponses: 3
    Dernier message: 06/07/2004, 10h21

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