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 :

[Vector] Adresse de l'objet d'un vecteur


Sujet :

C++

  1. #1
    Membre éprouvé Avatar de Polyfructol
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Avril 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Avril 2007
    Messages : 131
    Par défaut [Vector] Adresse de l'objet d'un vecteur
    Bonjour, j'ai un problème d'utilisation de vecteurs dans le cadre d'un petit jeu de casse brique.

    Pour résumer, le jeu contient une classe abstraite Object, sur laquelle dérivent 3 autres classes. Une classe Player, Ball et Brick.

    Ces 3 classes sont gérées par une classe ObjectManager qui contient un vecteur qui pointe sur tous les objets de la scène.

    La classe ObjectManager :
    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
    class ObjectManager
    {
    private:
        std::vector<Object *> list;
    public:
        ~ObjectManager();
        void addObject(Object*);
        Object* getObject(int i) { return list[i]; }
        int getSize() { return list.size(); }
    };
    ObjectManager::~ObjectManager()
    {
        while (!list.empty())
            list.pop_back();
    }
    void ObjectManager::addObject(Object *t_object)
    {
        list.push_back(t_object);
    }
    La déclaration des objets et l'ajout des objets dans ObjectManager :
    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
        // Quelque part dans le main ...
        // Déclaration des Objets de la scène. ->Objets(int position_x, int position_y)
        Player player(240, 460); // le player s'affiche en bleu
        Brick bricktest(50, 50); // Brique s'affiche en rouge
        Ball ball(320, 430);     // La balle s'affiche en rouge
     
        std::vector<Brick> bricklist; // Toutes les briques sont dans un vecteurs
        for (int i = 10; i < 620; i += 25)
            for (int j = 10; j < 300; j += 15)
                bricklist.push_back(Brick(i, j));
     
        // Ajout des objets précédents 
        objectmanager.addObject(&ball);
        objectmanager.addObject(&bricktest);
        objectmanager.addObject(&player);
     
        for (int i = 0; i < bricklist.size(); i++)
            objectmanager.addObject(&bricklist[i]); //<--- PAS BON, mais fonctionne ...
            // De plus les briques s'affichent en bleue, c'est la couleur de l'objet précédents soit player...
    Je soupçonne la dernière ligne d'être la cause de tout ça.

    Ce code compile, pas d'erreur avec MinGW, mais lors de l'affichage des briques, elles ne sont pas de la bonne couleur -> toutes les briques qui étaient dans le vecteur sont bleues, alors que la brique déclarée normallement est rouge (la couleur étant générée dans le constructeur), et ça rame bien.

    Voilà, donc je pense qu'il y a un gros problèmes dans la mémoire, mais je n'arrive pas a le régler. Surement une mauvaise utilisation du vecteur pour faire passé l'adresse dans la dernière ligne.

    Merci d'avance d'avoir lu !

    EDIT : Aïe, je me suis trompé de section, si un admin passe par ici, pourrait-il le déplacer dans la section SL & STL, merci.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Est-tu certain que le problème n'est pas quand tu mets les briques dans le vecteur ? Comment est défini le constructeur par recopie de cette classe ?

    Autrement, prendre l'adresse d'un élément dans le vecteur devrait marcher à condition que par la suite tu ne touches plus du tout au nombre d'élément dans le vecteur.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre éprouvé Avatar de Polyfructol
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Avril 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Avril 2007
    Messages : 131
    Par défaut
    Je n'ai pas défini de constructeur par recopie à vrai dire, je vais suivre cette piste en tout cas !

    Je montre un code plus explicite, il faut que je sache si c'est censé marcher, parce que dans mon cas ça ne marche pas (bon ça marche a moitié c'est pas normal quand même )

    Je déclare des objets qui sont tous dérivés de ma classe Object
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        // Déclaration des Objets de la scène
        Player player(240, 460);
        Ball ball(320, 430);
        Brick bricktest(200, 200);
     
        std::vector<Brick> bricklist;
        bricklist.push_back(Brick(260, 200)); // Je met une brique dans le vecteur
    J'envois leurs adresses dans le vecteur de la classe ObjectManager
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        objectmanager.addObject(&ball);
        objectmanager.addObject(&bricktest);
        objectmanager.addObject(&player);
        objectmanager.addObject(&bricklist.at(0)); // J'envois l'adresse du premier membre du vecteur
    Et là ça marche moyennement ... Alors que si je n'utilise pas le vecteur et place 30 briques (à la main), ça marche à merveille.

    Deux images pour expliquer la bizarrerie engendrée par ce truc :
    Si je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        objectmanager.addObject(&ball);
        objectmanager.addObject(&bricktest);
        objectmanager.addObject(&player);
        objectmanager.addObject(&bricklist.at(0));
    Ca m'affiche ça :


    Alors que si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        objectmanager.addObject(&bricktest);
        objectmanager.addObject(&player);
        objectmanager.addObject(&ball);
        objectmanager.addObject(&bricklist.at(0));
    J'obtiens :


    La brique du vecteur prend la couleur de l'objet situé avant elle !! alors que c'est pas possible, ça doit être rouge, le dessin du rectangle (dont la couleur) est dans le constructeur.

    Donc j'aimerais votre avis sur les deux petits morceaux de code au début du message. Si ce n'est pas un problème de vecteur, j'irais poster dans la rubrique consacré à la librairie graphique associée.

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Je n'ai pas défini de constructeur par recopie à vrai dire, je vais suivre cette piste en tout cas !
    Dans ton cas, le vecteur n'est pas responsable de la durée de vie des objets, donc le constructeur de copie, l'opérateur d'affectation et le destructeur par défaut conviennent, pas la peine de les redéfinir.

    Donc j'aimerais votre avis sur les deux petits morceaux de code au début du message.
    Tout a l'air correct, à condition que tu n'utilise pas l'objectmanager en dehors du bloc où sont déclaré les objets dont tu prend l'adresse. Si c'est le cas, alors l'erreur doit venir d'ailleurs dans le code.

  5. #5
    Membre éprouvé Avatar de Polyfructol
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Avril 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Avril 2007
    Messages : 131
    Par défaut
    Merci de la précision. Je n'utilise pas ObjectManager en dehors du bloc où je déclare les objets. Si c'est correct je n'y comprends plus rien.

    Je viens de faire la même chose en utilisant un tableau à double dimension. Et ça fonctionne bien. Mais je préfèrerais comprendre pourquoi avec mon vecteur ça marche pas.

    La déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        const unsigned int nb_bricks = 500;
        Brick **bricklist = new Brick*[nb_bricks];
        for(int i = 10, a = 0; i < 620; i += 25)
            for(int j = 10; j < 300; j += 15, a++)
                bricklist[a] = new Brick(i,j);
    Équivaut-elle à ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        std::vector<Brick> bricklist;
        for (int i = 10; i < 620; i += 25)
            for (int j = 10; j < 300; j += 15)
                bricklist.push_back(Brick(i, j));
    Et la connection à l'objectmanager
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        for(unsigned int i = 0; i < nb_bricks; i++)
            objectmanager.addObject(bricklist[i]);
    Équivaut-elle à ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        for(int i = 0; i < bricklist.size(); i++)
            objectmanager.addObject(bricklist.at(i));
    Parce que le résultat n'est pas le même.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Citation Envoyé par Polyfructol Voir le message
    La déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        const unsigned int nb_bricks = 500;
        Brick **bricklist = new Brick*[nb_bricks];
        for(int i = 10, a = 0; i < 620; i += 25)
            for(int j = 10; j < 300; j += 15, a++)
                bricklist[a] = new Brick(i,j);
    Équivaut-elle à ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        std::vector<Brick> bricklist;
        for (int i = 10; i < 620; i += 25)
            for (int j = 10; j < 300; j += 15)
                bricklist.push_back(Brick(i, j));
    Pas du tout.
    Partons du code avec le vecteur.
    Le code suivant est déjà plus proche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        const unsigned int nb_bricks = 500;
        Brick* bricklist = new Brick[nb_bricks];
        for (int i = 10; i < 620; i += 25)
            for (int j = 10; j < 300; j += 15)
                bricklist[i] = Brick(i, j);
    vector<T> n'est pas un tableau de pointeurs vers T, il s'agit d'un tableau de T, tout simplement.
    Dans ce code, par exemple, les briques sont défaut-construites puis ensuite l'opérateur d'affectation est appelé.
    En vrai néanmoins, ce n'est pas comme ça. La mémoire est non-initialisée puis quand on insère un élément celui est copié directement dans la mémoire.

    C'est donc plutôt comme ceci :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        const unsigned int nb_bricks = 500;
        Brick* bricklist = static_cast<Brick*>(::operator new(sizeof(Brick)*nb_bricks));
        for (int i = 10; i < 620; i += 25)
            for (int j = 10; j < 300; j += 15)
                new(bricklist[i]) Brick(Brick(i, j));
    Citation Envoyé par Polyfructol Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        for(int i = 0; i < bricklist.size(); i++)
            objectmanager.addObject(bricklist.at(i));
    Ce code ne compile pas a priori, il manque un &.

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Sylvain Togni Voir le message
    Dans ton cas, le vecteur n'est pas responsable de la durée de vie des objets, donc le constructeur de copie, l'opérateur d'affectation et le destructeur par défaut conviennent, pas la peine de les redéfinir.
    Le std::vector<Object *> list; n'est certes pas responsable de la durée de vie, mais il y a un autre vecteur dans le code, qui lui utilise le constructeur de copie, c'est le std::vector<Brick> bricklist;
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ObjectManager::~ObjectManager()
    {
        while (!list.empty())
            list.pop_back();
    }
    Attention, ici tu n'effaces pas du tout tes Objets !
    Il te faut un delete, sinon tu auras une belle fuite de mémoire.

    Une autre solution pourrait être d'utiliser les conteneur de pointeurs intelligents de Boost qui t'éviteront de remplir ce destructeur.

  9. #9
    Membre éprouvé Avatar de Polyfructol
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Avril 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Avril 2007
    Messages : 131
    Par défaut
    Merci à vous, j'ai enfin réussi à régler mon problème, et c'était tout bête en plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        std::vector<Brick*> bricklist;
        for (float i = 10; i < 620; i += 25)
            for (float j = 10; j < 300; j += 15)
                bricklist.push_back(new Brick(i, j)); // au lieu de .push_back(Brick(i, j));
    ...
        // Suppression du tableau de brique
        for(int i = 0; i < bricklist.size(); i++)
            delete bricklist[i];
    Tout fonctionne à ce niveau. Mais j'ai un doute pour la suppression des briques...
    Citation Envoyé par loufoque
    C'est donc plutôt comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        const unsigned int nb_bricks = 500;
        Brick* bricklist = static_cast<Brick*>(::operator new(sizeof(Brick)*nb_bricks));
        for (int i = 10; i < 620; i += 25)
            for (int j = 10; j < 300; j += 15)
                new(bricklist[i]) Brick(Brick(i, j));
    Merci pour cette solution, cependant, ne maitrisant pas vraiment ces "aspects" du C++ je n'ai pas réussi à le faire marcher.
    Ca me donne une erreur de compilation là : new(bricklist[i]) Brick(Brick(i, j));
    Citation Envoyé par loufoque
    Ce code ne compile pas a priori, il manque un &.
    En effet, erreur de frappe en recopiant.
    Citation Envoyé par poukill
    Attention, ici tu n'effaces pas du tout tes Objets !
    Il te faut un delete, sinon tu auras une belle fuite de mémoire.
    En fait, la classe objectmanager ne gère pas la mémoire des objets pointés par le vecteur list. Donc ce que j'ai fait ne sert a rien, les objets sont créés puis supprimés à l'extérieur de la classe objectmanager, je vais supprimer le destructeur.

    Voilà, merci de vous être penché sur mon cas

  10. #10
    screetch
    Invité(e)
    Par défaut
    loufoque ton code contenant un new me parait bien compliqué

Discussions similaires

  1. Réponses: 21
    Dernier message: 03/06/2010, 18h26
  2. operator<< : n'affiche que l'adresse de l'objet..
    Par skrenit0 dans le forum C++
    Réponses: 10
    Dernier message: 30/04/2006, 17h25
  3. [POO] copie de l'adresse d'un objet
    Par Wormus dans le forum Langage
    Réponses: 11
    Dernier message: 30/01/2006, 14h48
  4. Tri d'objets dans un vecteur
    Par Jahjouh dans le forum C++
    Réponses: 5
    Dernier message: 26/01/2006, 18h23
  5. destruction d'objets dans un vecteur
    Par titouille dans le forum C++
    Réponses: 12
    Dernier message: 28/07/2005, 19h20

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