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 :

std::multiset et foncteur


Sujet :

C++

  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut std::multiset et foncteur
    Bonjour ( re ).

    J'ai un petit pb avec un tri d'image. J'utilise multiset pour classer les images en fonction d'un z order, et d'un foncteur.
    Ca marche qu'à moitié : sans raison apparente, l'ordre se met de temps en temps à être mauvais.

    voici ma class qui est utilisé dans le multiset :

    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
     
     
    class IE : public sf::Drawable
    {
     
    friend struct Fonctor;
     
    public :
     
        void setTexture ( const sf::Texture *texture ) ;
        void setVertex( sf::Vertex vertex[4]) ;
        void setZ ( float z ) ;
     
        void draw ( sf::RenderWindow &window ) ;
     
    protected :
     
        virtual void draw ( sf::RenderTarget& target , sf::RenderStates states ) const
        {
                states.texture = _texture ;
                target.draw ( _vertex , 4 , sf::Quads , states ) ;
        }
     
        const sf::Texture                                       *_texture ;
        sf::Vertex                                              _vertex[4] ;
        float                                                   _z ;
     
    };
     
    struct Fonctor
    {
     
       bool operator() ( const IE* one , const IE* two ) const
       {
            return one -> _z < two -> _z ;
       }
     
    };
    et voici l'utilisation du multiset :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private :
     
        std::multiset < IE* , Fonctor >                                 _IE ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    void System::print ( sf::RenderWindow* window )
    {
        window -> setView( _view ) ;
        for ( auto& it : _IE )
        {
            window -> draw ( *it ) ;
        }
    }
    j'utilise des pointeurs afin que chaque objet puisse gérer directement ses IEs. Un objet mobile doit par contre réinsérer a chaque fois son IE pour qu'elle se range correctement, afin de se positionner devant ou derrière ses camarades IEs de la bonne façon. cela donne ceci :
    (sachant que ma class IE_Word est une IE_Entity qui contient en public l'IE et toutes les informations nécessaire a sa bonne gestion : l'animation, son positionnement par rapport à l'Object ect... ).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    void Graphics::reload()
    {
        for ( auto& it : _IE_Word )
        {
            it._z = *_y + it._shiftPosition.y + it._z ;  //_y est un pointeur vers le _y de l'objet contenu dans le _physics de l'objet.
            it._IE.setZ ( it._z ) ;
            _system -> clean ( &it._IE ) ;
            _system -> add ( &it._IE ) ;
        }
    }
    et voici ma fonction clean qui détruit le ptr du multiset ( ça vient peut être de là ).

    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
     
     
    void System::clean( IE* ie )
    {
     
        for ( std::multiset < IE* > :: iterator it = _IE.begin () ; it != _IE.end() ; it ++ )
        {
            if ( ie == *it )
            {
                _IE.erase ( it ) ;
                it = _IE.begin () ;
            }
        }
     
    }
    Mes thermes utilisés ne sont probablement pas des plus académique, mais j'espère qu'ils sont suffisamment clair pour être compréhensible.
    Si vous avez des commentaires, reflexions sur cette mise en place en terme de programmation, je suis toujours preneur.

    Merci si vous pouvez m'aider

  2. #2
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Il est difficile de répondre avec les morceaux de code que tu donnes. En particulier, j'ai l'impression qu'il y a des variables globales qui se promènent (_IE, _IE_WORD)?
    Par ailleurs je ne comprends pas l'intérêt du multiset si tu remplaces l'ordre régulièrement et intégralement.
    Pourquoi ne pas passer par un vecteur que tu tries, plutôt que de retirer et de réinsérer tous les éléments du multiset?
    Ce type de structure est utile lorsque les insertions/suppressions sont rares et les recherches fréquentes.

  3. #3
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    je pense que le problème vient du clean/add des élements. La fonction membre erase() de la classe multiset de touche pas à la mémoire, il modifie juste l'indexation. Si l'on veut réellement supprimer un élément d'un conteneur de la STL, il faut utiliser l'idiome erase/remove.

    Cela dit, ce code est très dangereux.
    -> Des pointeurs nus de partout et aucun respect de la const-conformité, c'est l'assurance d'une perte de contrôle totale du code. D'autant plus que tu utilises des pointeurs sur des objets qui arrivent d'une lib externe (ici la sfml) et qui te sont fournis sous forme de référence; c'est limite du terrorisme.
    -> Les accesseurs/mutateurs c'est le mal (c'est le symptôme d'erreurs de conceptions, c'est donc un arbre qui cache une forêt).
    -> Si tu tiens à effacer ta liste et la recréer à chaque fois (ce qui, à priori, devrait être évité), alors efface tout d'un coup et re-remplis là ensuite élément par élément.

    Citation Envoyé par mazertys17
    Mes thermes utilisés ne sont probablement pas des plus académique
    Les thermes romains n'étaient pas plus académiques que les termes que tu utilises.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  4. #4
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Merci pour vos réponses

    En effet, un vector et std::sort seraient peut être plus approprié. Je vais essayer de mettre ca en place.

    -> Des pointeurs nus de partout et aucun respect de la const-conformité, c'est l'assurance d'une perte de contrôle totale du code. D'autant plus que tu utilises des pointeurs sur des objets qui arrivent d'une lib externe (ici la sfml) et qui te sont fournis sous forme de référence; c'est limite du terrorisme.
    houla ca me fait un peu peur

    perte contrôle totale du code ? c'est à dire ?
    dites moi si je fais fausse route :
    Dans mon cas, je n'ai qu'une class "Graphics" dans tout le programme, susceptible d'avoir des IE, et va se contenter d'envoyer la référence de son/ses IE en tant que pointeurs au seul multiset/vector du system susceptible d'en contenir également, et qui a pour mission de les afficher.
    Ces "Graphics" demandent systématiquement leur effacement avant destruction, et les objets qui contiennent un Graphics feront de même avec le Graphics... Mon objectif était :

    -d'avoir un multiset/vector qui contienne des objets les plus petits possible. ( en pensant que ca optimiserait l'affichage, vu qu'il est appelé à chaque boucle, et qu'il peut y en avoir moult ).

    -de pouvoir contrôler directement les IE depuis les Graphics/Objects, sans avoir à les re-bidouiller, puisque leurs pointeurs sont déjà dans le vector central qui les affiche.

    -enfin, de pouvoir justement trier toutes les images au fur et à mesure qu'elles sont ajoutés, quelque soit l'ordre de l'update des object qui les contiennent.

    Qu'est-ce que je risque concrètement en faisant cela ? Aurais-je intérêt à utiliser des unique_ptr/shared_ptr ou autre à la place ?
    Est-ce plus intéressant d'utiliser, par ex, directement la class Graphies pour l'affichage ?

    Merci pour l'aide

  5. #5
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Comme déjà dit, pas mal de trucs qui vont pas.
    Mais en particulier ça :
    Citation Envoyé par mazertys17 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void Graphics::reload()
    {
        for ( auto& it : _IE_Word )
        {
            it._z = *_y + it._shiftPosition.y + it._z ;  //_y est un pointeur vers le _y de l'objet contenu dans le _physics de l'objet.
            it._IE.setZ ( it._z ) ;
            _system -> clean ( &it._IE ) ;
            _system -> add ( &it._IE ) ;
        }
    }
    Un std::multiset contient des éléments constants (depuis C++11 ? Dans tous les cas la clef DOIT être constante).

    Hors tu modifies la clef.

    La seule façon de modifier proprement la clef d'un élément c'est de le supprimer, modifier, puis ré-insérer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    auto it = std::begin(_IE_Word); // on récup un iterateur sur l'élément à modifier
    auto elt = *it; // on copie l'élément
    elt._z = 42; // la copie peut être modifiée
    _IE_Word.erase(it); // on supprime l'original
    _IE_Word.insert(elt); // on ajoute le nouvel élément
    Vu que tu modifies tous les éléments, faire un nouveau std::multiset est plus simple / rapide.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::multiset<IE> ies;
    for(auto elt: _IE_Word) { // on copie elt, pour pouvoir le modifier
        elt.z = 42; // modification
        ies.insert(elt); // insert dans le nouveau set
    }
    _IE_Word = std::move(ies); // on remplace l'ancien par le nouveau, à jour.
    Si tu dois supprimer / créer des std::multiset de mannière régulière, un std::vector sera certainement plus efficace.

    Une implémentation à base de std::vector peut 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
    28
    29
    30
    31
    32
    33
    struct IECmp {
        bool operator()(IE const& a, IE const& b) const { return a.z < b.z; }
    };
     
    struct MySet {
       IECmp m_cmp;
       std::vector<IE> m_data;
     
       void insert(T const& item) {
          auto itInsert = std::lower_bound(..., m_cmp) // trouver l'endroit où insérer
          m_data.push_back(item); // insertion à la fin
          std::rotate(itInsert, std::end(m_data), std::end(m_data)); // on swap les éléments pour maintenir l'ordre
       }
     
       voir remove(T const& item) {
          // trouver le range dans lequel se trouve l'elt
          auto itBegin = std::lower_bound(..., m_cmp);
          auto itEnd = std::upper_bound(..., m_cmp);
          auto itDelete = std::find(itBegin, itEnd, item); // recherche linéaire dans ce range
          std::rotate(itDelete, itDelete + 1, std::end(m_data)); // on met l'élément à supprimer au fond
          m_data.pop_back(); // on le vire
       }
     
       void update(T const& item, int newZ) {
          // trouver le range dans lequel se trouve l'elt
          auto itBegin = std::lower_bound(..., m_cmp);
          auto itEnd = std::upper_bound(..., m_cmp);
          auto itElt = std::find(itBegin, itEnd, item); // recherche linéaire dans ce range
          auto itNewPlace = std::lower_bound(... , m_cmp); // on trouve où l'élément doit être placé après modification
          *itElt.z = newZ;
          std::rotate(...); // on réarrange les éléments pour maintenir l'ordre
       }
    };
    @r0d: c'est remove qui ne supprime pas réellement.

  6. #6
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    perte contrôle totale du code ? c'est à dire ?
    C'est à dire que si ton programme grandit, au bout d'un moment il sera impossible à maintenir (debugger, tester, améliorer, etc.). Le problème des pointeurs nus c'est qu'ils ajoutent des dépendances fortes entre les modules, sans spécifier la propriété (qui possède qui, les cycles de vie, etc.). Et le problème d'un code qui ne respecte pas la const-conformité, c'est qu'au plus le développement du logiciel avance, au plus il est difficile de savoir qui fait quoi, et au bout d'un moment, ça devient un réel problème.

    Citation Envoyé par mazertys17 Voir le message
    Aurais-je intérêt à utiliser des unique_ptr/shared_ptr ou autre à la place ?
    De façon générale, et puisque tu n'utilises pas de bibliothèque C, tu ne dois pas utiliser de pointeur (qu'ils soient intelligents ou nus) si tu ne fais pas de polymorphisme. Utilise plutôt les références et le déplacement (move semantic).
    A noter également: pour bien utiliser une bibliothèque, il faut comprendre un peu sa philosophie et essayer de la respecter. Regarde un peu du code qui utilise la sfml (par exemple, prends une petite heure et regarde les tutos), et tu verras que la sfml utilises abondamment les références, et pas de pointeurs (jamais). Accessoirement, la sfml utilises d'autres idiomes très puissants, comme NVI, RAII, etc, mais c'est un autre débat.

    Pour le reste, lis bien attentivement ce qu'a écrit Iradrille, il a parfaitement cerné ton problème, et son dernier message y répond clairement.

    Citation Envoyé par Iradrille Voir le message
    @r0d: c'est remove qui ne supprime pas réellement.
    Effectivement. Merci pour la correction.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  7. #7
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Merci pour ta réponse, rod.

    Je suis débutant, alors il y a bien des choses que je n'ai pas parfaitement cerné...

    tu ne dois pas utiliser de pointeur (qu'ils soient intelligents ou nus) si tu ne fais pas de polymorphisme
    Oui, vu que j'utilise l'héritage, j'utilise des ptr ( en l’occurrence des shared_ptr ), donc là dessus on est d'accord...( sauf erreur ).

    Par contre j'ai une class qui n'est pas "polymorphique", qui est la class "Graphics", contenue dans mes objets, qui contient une IE, qui elle même, contient un pointeur de texture, et celui ci me parait inévitable ( vu que la texture doit être partagé par plusieurs objets, qui sont graphiquement identiques ). Peut-on faire différemment dans ce cas ?

    là ou j'ai du mal à voir comment je pourrais faire autrement, c'est pour l'affichage des IE : vue que mes objets sont crées en fonction des besoins du jeu et non de leur ordre graphic ( le z order ), il faut les trier séparément. A moins que je trie carrément les objets eux même avec le z order ( peut être est-ce la solution?? ), je ne vois pas comment je peux faire autrement, sinon, que de les envoyer en pointeur à un vector qui lui, va les trier dans le bon ordre. Car dans ce cas on ne peux pas faire un vector de référence ( sauf erreur ).
    A moins là encore que je ne mette pas l'IE elle même dans mon Graphics, mais dans le vector, et qu'au contraire le graphics garde la référence ? ( ca me parait bizard ).

    c'est qu'au plus le développement du logiciel avance, au plus il est difficile de savoir qui fait quoi, et au bout d'un moment, ça devient un réel problème.
    Même dans mon cas ? c'est a dire que je n'ai qu'une class Graphic dans tt le programme susceptible d'avoir des IE et qu'un vector dans le system qui les affiche ?

    Merci pour votre aide qui m'est précieuse, car je suis au début de la conception de mon programme, et il faut qu'il soit le plus fiable possible pour la suite.

  8. #8
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    Oui, vu que j'utilise l'héritage, j'utilise des ptr ( en l’occurrence des shared_ptr ), donc là dessus on est d'accord...( sauf erreur ).
    Ok alors, pour être plus précis, l'utilisation de pointeurs est indispensable dans le cas de conteneur générique contenant des objets polymorphes. Les conteneurs de la STL sont génériques, et il est rarissime d'avoir besoin d'autres formes de conteneurs (comme les listes de type par exemple). On peut cacher l'utilisation des pointeurs en passant par un Cheshire Cat (bridge), mais ce n'est pas forcément utile. Je dis ça pour ta culture.
    Par contre, je ne sais pas si cela correspond à ton cas, car je ne comprends pas ton code. Tu devrais utiliser des noms de variables et de classes plus explicites. IE, Graphics, etc, ça n'a aucun sens pour quelqu'un qui ne connait pas parfaitement ton code.

    Citation Envoyé par mazertys17 Voir le message
    Par contre j'ai une class qui n'est pas "polymorphique", qui est la class "Graphics", contenue dans mes objets, qui contient une IE, qui elle même, contient un pointeur de texture, et celui ci me parait inévitable ( vu que la texture doit être partagé par plusieurs objets, qui sont graphiquement identiques ). Peut-on faire différemment dans ce cas ?
    Je ne comprends pas ton design. Mais j'utilise régulièrement la SFML et ce que je fais lorsque j'ai des textures partagées, j'utilise des références plutôt que des pointeurs. Je ne sais pas si ça va cadrer avec ton programme, mais je t'explique:

    Basiquement, j'ai un conteneur de textures. Appelons-le TextureContainer. Typiquement, c'est une std::unordered_map<int, sf::Texture>, où le int est l'identifiant de la texture. Si tu n'as pas de grosses contraintes de performances (encore que ce n'est pas forcément vrai, il faudra que je fasse des tests là-dessus un jour), tu peux remplacer l'identifiant par une chaine de caractères (string). Généralement, mon TextureContainer est un simple alias (using TextureContainer = std::unordered_map<int, sf::Texture>). Mais si besoin, on peut l'encapsuler dans une classe dédiée.

    Quelque part dans ton code, tu vas charger tes textures; c'est à dire remplir ton TextureContainer. En général, on préfère charger toutes les textures d'un coup. Ensuite, pour accéder à tes textures, tu peux utiliser l'opérateur [], qui te renvoie une référence vers ta texture: const sf::Texture & example = texture_container[id]; Ainsi, il n'y a ni copie, ni pointeur.

    Du coup, lorsque tu as besoin de ta texture, tu récupères la référence. Par exemple, si je veux faire une classe Button qui contient (entre-autres) une texture chargée depuis un fichier png. Je peux faire ainsi (code partiel, simplifié et non testé, juste pour l'idée):
    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
    class Button : public sf::Drawable
    {
    public:
       Button() = delete; // on a besoin du TextureContainer pour contruire un bouton
     
       Button(const TextureContainer & texture_container)
       : texture_(texture_container[42]) // 42 est l'identifiant de la texture pour les boutons
       {
          sprite_.setTexture(texture_);
       }
     
       void draw(sf::RenderTarget & context) const
       {
          context.draw(sprite_);
       }
     
    private:
       const sf::Texture & texture_;
       sf::Sprite sprite_;
    };
    Citation Envoyé par mazertys17 Voir le message
    là ou j'ai du mal à voir comment je pourrais faire autrement, c'est pour l'affichage des IE : vue que mes objets sont crées en fonction des besoins du jeu et non de leur ordre graphic ( le z order ), il faut les trier séparément. A moins que je trie carrément les objets eux même avec le z order ( peut être est-ce la solution?? ), je ne vois pas comment je peux faire autrement, sinon, que de les envoyer en pointeur à un vector qui lui, va les trier dans le bon ordre. Car dans ce cas on ne peux pas faire un vector de référence ( sauf erreur ).
    A moins là encore que je ne mette pas l'IE elle même dans mon Graphics, mais dans le vector, et qu'au contraire le graphics garde la référence ? ( ca me parait bizard ).
    Je m'excuse, mais je ne comprends pas grand-chose à ce que tu dis là. Qu'est-ce qu'un IE? Qu'est-ce qu'un Graphics?

    Si tes objets graphiques doivent être construits et détruits régulièrement, alors:
    1/ il vaut mieux utiliser un conteneur plus dynamique, comme une list par exemple. Tout ce qui est associatif (set et map) est très peu dynamique (en fait ce sont des tree; des red-black tree pour être exact).
    2/ l'idéal c'est que ton conteneur soit toujours trié, c'est à dire que tu n'aies pas à faire le tri "à la main lorsque tu estimes que c'est le moment de le faire". Pour que ton conteneur soit toujours trié, il faut que chaque modification (ajout et suppression d'élément) soit faite de façon à ce que ce conteneur reste trié (ici intervient la notion d'invariant, je précise pour ta culture).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  9. #9
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Ok, merci pour ta réponse.

    Une IE est une Image Entity ( dsl j'ai oublié de préciser ), hérité de sf:rawable.
    Un Graphics est une class qui gère les IE : l'animation, la position, couleur etc...

    J'ai toujours du mal avec les références...Dans ton cas, la texture peut être utilisée pas plusieurs objets en même temps ? Pour ma part, si j'essaye de mettre une texture référence et non en pointeur dans mon IE, ca ne compile pas...il me dit :

    "error: use of deleted function "IE::IE()' " dans le constructeur.

    ( en tout cas je fonctionne pareil pour le chargement des texture, avec un std::map < std::string name , sf::Texture* > , à part que ma texture est justement un ptr ).

  10. #10
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    J'ai toujours du mal avec les références...
    C'est pourtant une notion fondamentale en C++, et préférable, de loin, aux pointeurs.

    Citation Envoyé par mazertys17 Voir le message
    Dans ton cas, la texture peut être utilisée pas plusieurs objets en même temps ?
    Oui. Une référence c'est juste l'adresse en mémoire de ton objet. Finalement, c'est un peu comme un pointeur. La différence fondamentale entre les deux c'est qu'un pointeur peut être null, alors qu'une référence "pointe" obligatoirement sur quelque chose.

    Citation Envoyé par mazertys17 Voir le message
    Pour ma part, si j'essaye de mettre une texture référence et non en pointeur dans mon IE, ca ne compile pas...il me dit :

    "error: use of deleted function "IE::IE()' " dans le constructeur.
    A première vue, cela n'a rien à voir avec pointeur vs référence. Là il te dit juste que le constructeur par défaut de la classe IE a été delete, mais qu'il en a besoin.

    Citation Envoyé par mazertys17 Voir le message
    à part que ma texture est justement un ptr ).
    Mais c'est une différence fondamentale.
    Il faut comprendre que la philosophie du C++, et la raison de son existence, c'est de se libérer de la gestion manuelle de la mémoire (malloc, free, etc., et donc, par extension, new et delete). Le problème d'un pointeur, surtout un pointeur nu, c'est que tu dois gérer manuellement sa durée de vie avec un new et un delete, avec tous les problèmes que ça engendre. En utilisant une référence, tu n'as plus besoin de te préoccuper de cette durée de vie, car c'est géré automatiquement par les mécanismes spécifiques du langage c++: l'allocation est sécurisée par le fait qu'une référence est forcément valide (sinon ça ne compile pas), et la libération est gérée par le fait que l'objet est sur la pile, donc libéré automatiquement lorsqu'on sort de sa portée (scope).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

Discussions similaires

  1. Réponses: 1
    Dernier message: 15/04/2011, 14h06
  2. Améliorations de std::for_each avec les foncteurs
    Par Invité dans le forum Débuter
    Réponses: 15
    Dernier message: 13/05/2010, 12h46
  3. [std::multiset] 2eme Parameter
    Par ZaaN dans le forum SL & STL
    Réponses: 5
    Dernier message: 24/05/2007, 16h39
  4. Réponses: 18
    Dernier message: 03/07/2006, 15h53
  5. [std::list][find_if] problème avec mes foncteurs
    Par n!co dans le forum SL & STL
    Réponses: 12
    Dernier message: 04/02/2005, 11h56

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