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 :

delete, vector et destructeur


Sujet :

C++

  1. #1
    Membre confirm�
    Homme Profil pro
    D�veloppeur du dimanche
    Inscrit en
    F�vrier 2013
    Messages
    154
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur du dimanche

    Informations forums :
    Inscription : F�vrier 2013
    Messages : 154
    Par d�faut delete, vector et destructeur
    Bonjour,

    Y a-t-il une fuite de m�moire dans le code suivant ?

    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
    std::vector<void*> components;
     
    struct Component
    {
        unsigned index;
     
        Component() : index(components.size()) {};
     
        ~Component()
        {
            std::swap(components[index],components.back());
            components.pop_back();
        }
    };
     
    struct Position : Component {};
     
    struct Name : Component {};
     
    int main()
    {
        components.push_back(new Position);
        components.push_back(new Name);
        components.push_back(new Name);
        components.push_back(new Position);
        components.push_back(new Name);
     
        Name* e = static_cast<Name*>(components[2]);
        delete e;
     
        return 0;
    }
    Normalement, on fait d'abord delete, puis ensuite on enl�ve l'�l�ment dans le vector, mais dans mon cas, je ne sais pas trop comment �a va se passer �tant donn� que delete appelle le destructeur, o� justement je supprime l'�l�ment du vector


  2. #2
    Futur Membre du Club
    Homme Profil pro
    Coll�gien
    Inscrit en
    Avril 2014
    Messages
    5
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Coll�gien

    Informations forums :
    Inscription : Avril 2014
    Messages : 5
    Par d�faut
    Est-ce que ce code fuit? Il me semble que non.

    Est-ce que ce code est donc bien fichu? Oh que non.

    Une classe qui fait r�f�rence en dur � une variable globale qui contiendra toutes ses futures instances? Mmh. Pas s�r que ce pattern connaisse un grand succ�s.

    Si tu expliques quel est le but de ton code, on peut t'orienter vers une solution plus standard.

  3. #3
    Membre confirm�
    Homme Profil pro
    D�veloppeur du dimanche
    Inscrit en
    F�vrier 2013
    Messages
    154
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur du dimanche

    Informations forums :
    Inscription : F�vrier 2013
    Messages : 154
    Par d�faut
    Bah, faut dire aussi, c'est un code minimal, en pratique y aura pas de variable globale, par contre elle contiendra effectivement toutes mes instances, pour �pargner ma m�moire cache.

    Le but du code ? En gros.

    J'ai ce vector de components, et un autre vector (system) que je n'ai pas fait figurer ici, qui contiendra des pointeurs sur ces components. Je veux pouvoir supprimer facilement ces components depuis system sans avoir � tenir un registre o� j'enregistre � quelle position j'ai enregistr� tel component.

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Un vector de void* c'est pas s�rieux �a

    Citation Envoy� par MrPchoun Voir le message
    par contre elle contiendra effectivement toutes mes instances, pour �pargner ma m�moire cache.
    Cette opitmisation me para�t bien pr�matur�e. Early optimization is the root of all evil. Avant d'optimiser, on fait du profiling. Pour l'instant, tu es en au design, pas encore au profiling. En plus, elle ne fonctionne pas : si tu stockes des pointeurs, les components ne seront pas contigus et ton optimisation de cache ne sert � rien ! Apr�s je suppose que Component est polymoprhique, dans lequel cas tu n'as pas le choix, tu ne pourras pas les stocker de mani�re contigue facilement.

    Citation Envoy� par MrPchoun Voir le message
    Je veux pouvoir supprimer facilement ces components depuis system sans avoir � tenir un registre o� j'enregistre � quelle position
    Et pourtant, tu le fais : chaque component enregistre son indice. En plus, �a ne fonctionne pas : si tu supprimes un �l�ment au milieu du vecteur, �a va te c�uter cher car tous les �l�ments suivants seront d�plac�s, et en plus leur indices ne seront plus bon, et les r�f�rences stock�es dans ton system ne le seront plus non plus.

    Pour faire le bon choix de la collection, il faut �valuer ton besoin:

    • Si tu veux pouvoir supprimer un �l�ment de mani�re peu co�teuse sans invalider les autres r�f�rences et que tu ne fais pas ou peu de parcours de la liste : std::list
    • SI tu veux faire des parcours de liste efficace : std::vector
    • Si tu veux faire les deux : tu es niqu�, mais il est probable que std::vector soit meilleur.


    Ensuite, c'est une assez mauvaise id�e d'utiliser des pointeurs nus, car non seulement c'est risqu�, mais en plus tu ne d�finis pas clairement la politique de propri�t� de tes composants. Qui est propri�taire de l'objet ?

    • Si c'est une propri�t� partag�e entre les syst�mes, consid�re l'usage de std::shared_ptr
    • Si la collection "globale" est propri�taire (c'est � dire que le supprimer de la liste est �quivalent � le supprimer compl�tement), utilise std::unique_ptr


    Et enfin, las but not least, est-ce que tu ne gagnerais pas du temps � utiliser du code existant ?

  5. #5
    R�dacteur/Mod�rateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : Canada

    Informations professionnelles :
    Activit� : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par d�faut
    tu mets 5 �l�ments via new, tu les mets en void*, t'en delete 1 seul, sans destructeur virtuel
    et tu te demandes si �a fuit ?
    Pensez � consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation r�seau ?
    Aucune aide via MP ne sera dispens�e. Merci d'utiliser les forums pr�vus � cet effet.

  6. #6
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (�le de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par d�faut
    Et ne parlons m�me pas du fait que tu ne l'a pas enlev� du vector.

    Ton id�e a un nom: le pattern flyweight.

  7. #7
    Membre confirm�
    Homme Profil pro
    D�veloppeur du dimanche
    Inscrit en
    F�vrier 2013
    Messages
    154
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur du dimanche

    Informations forums :
    Inscription : F�vrier 2013
    Messages : 154
    Par d�faut
    @jblecanard :

    Et pourtant, tu le fais : chaque component enregistre son indice. En plus, �a ne fonctionne pas : si tu supprimes un �l�ment au milieu du vecteur, �a va te c�uter cher car tous les �l�ments suivants seront d�plac�s, et en plus leur indices ne seront plus bon, et les r�f�rences stock�es dans ton system ne le seront plus non plus.
    Ben pas vraiment, c'est justement pour �a que j'utilise la m�thode swap + pop_back :
    - �a coute pas cher en temps
    - �a d�place juste ce qu'il faut

    Les vector me paraissent mieux, justement parce que je fais beaucoup d'it�rations.

    La solution shared_pointer, bien que tr�s �l�gante, ne m'impressionne pas beaucoup au niveau des performances (x10 environ en temps), il me faut donc une autre solution.

    Et enfin, las but not least, est-ce que tu ne gagnerais pas du temps � utiliser du code existant ?
    Moi, je code surtout pour me faire plaisir. �a change tout mon rapport au temps ;-)

    @bousk :

    Ben �coute, merci d'apporter de la profondeur au d�bat. N'h�site surtout pas.

    @leternel :

    Merci, je vais aller creuser de ce c�t� l�.

  8. #8
    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,
    Citation Envoy� par MrPchoun Voir le message
    @jblecanard :



    Ben pas vraiment, c'est justement pour �a que j'utilise la m�thode swap + pop_back :
    - �a coute pas cher en temps
    - �a d�place juste ce qu'il faut

    Les vector me paraissent mieux, justement parce que je fais beaucoup d'it�rations.

    La solution shared_pointer, bien que tr�s �l�gante, ne m'impressionne pas beaucoup au niveau des performances (x10 environ en temps), il me faut donc une autre solution.
    Heuu... tu as fais des mesures concr�tes et surtout correcte pour citer ce chiffre?

    Es-tu sur que la diff�rence de temps soit si importante ?

    Es-tu sur que la diff�rence ne vient pas de la n�cessit� d'augmenter la taille de ton tableau lors de l'ajout d'�l�ment

    Car, il faut bien avouer que std::shared_ptr est, effectivement, une solution qui occasionne forc�ment une perte de performances, � cause du "comptage de r�f�rences" qu'il implique afin de s'assurer que le dernier co-responsable d'un pointeur en vie s'occupe de le d�truire.

    Mais de l� � dire que ce comptage de r�f�rence occasionne une telle perte, il y a de la marge : le comptage de r�f�rence est une op�ration � priori atomique, ce qui implique qu'il devrait s'effectuer en un temps minimum

    Ceci dit, les std::unique_ptr ne pr�sentent pas cet inconv�nient et repr�sente, � mon sens, le type de pointeurs intelligent � utiliser "par d�faut", dans le sens o� on devrait commencer par utiliser std::unique_ptr et ne passer � un std::shared_ptr que si le besoin s'en fait sentir

    std::unique_ptr ne pr�sente aucun overhead au niveau des performances, vu qu'il ne fait qu'une seule et unique chose : appeler delete sur le pointeur sous-jascent lorsqu'il est d�truit (chose que tu devrais de toutes mani�res faire avant de perdre d�finitivement l'adresse � laquelle se trouve l'objet allou� dynamiquement

    Moi, je code surtout pour me faire plaisir. �a change tout mon rapport au temps ;-)
    Bref, tu te tapes sur la t�te avec un marteau en disant "mais ca fait tellement de bien quand ca s'arr�te"
    @bousk :

    Ben �coute, merci d'apporter de la profondeur au d�bat. N'h�site surtout pas.
    Et pourtant, il n'a pas tord...

    void * est d'usage tr�s r�gulier en C, mais est une v�ritable catastrophe en C++ qui propose un tas d'alternatives �l�gantes et bien plus s�curisantes (h�ritage public, paradigme g�n�rique, j'en passe et de meilleures)

    La mani�re dont il s'est exprim� n'est sans doute pas celle te permet le plus facilement de trouver la solution � ton probl�me, mais elle a l'avantage de pointer exactement ton probl�me du doigt
    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

  9. #9
    Membre confirm�
    Homme Profil pro
    D�veloppeur du dimanche
    Inscrit en
    F�vrier 2013
    Messages
    154
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur du dimanche

    Informations forums :
    Inscription : F�vrier 2013
    Messages : 154
    Par d�faut
    Heuu... tu as fais des mesures concr�tes et surtout correcte pour citer ce chiffre?
    J'avais fait des mesures, oui. Apr�s, le chiffre de 10 �tait peut �tre un peu gros, mais je me souviens de quelque chose d'assez �norme, qui m'a rebut� direct, pour �a que j'ai mis de c�t� la m�thode smart pointer.

    Je vais r�-exposer mon probl�me, parce que les solutions propos�es ne me permettent vraiment pas d'y r�pondre.

    Le probl�me avec toutes les impl�mentations d'Entity Component System que j'ai pu trouver (y compris anax), ce que toutes proc�daient � peu pr�s de la m�me mani�re :
    Pour chaque entity
    --Pour chaque system
    ----Si l'entity a les components que le system requiert
    ------get ces components
    ------update ces components

    J'aimerais faire quelque chose qui demanderait moins d'it�rations inutiles, du coup j'ai eu l'id�e de stocker dans chaque syst�me un vector de pointeurs vers les components des entity. Je d�veloppe :

    L'entit� A a les components Sant�, Position et Name
    L'entit� B a les components Position et Name
    L'entit� C a juste le component Position

    On pourrait stocker les entit�s de la mani�re suivante :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    map<int,map<std::type_index,Component*>> entities.
    Exemple : entities[3][typeid(Position)] = new Position; // On ajoute le component Position � l'entit� 3

    Le system S traite les entit�s qui poss�dent les components Position et Name, il traitera donc les entit�s A et B
    Eh bien dans S, il y aura un vector de pointeurs vers components (vector<void*> ou vector<Component*>, peu importe)
    en [0], il pointera vers le component Position de l'entit� A
    en [1], il pointera vers le component Name de l'entit� A
    en [2], il pointera vers le component Position de l'entit� B
    en [3], il pointera vers le component Name de l'entit� B

    La fonction d'update g�re toute seule tout �a.

    Du coup, niveau algo, �a donne quelque chose du style
    Pour chaque system
    --get les components qui vont bien ([0] et [1] par exemple)
    --update ces components

    C'est quand m�me plus rapide niveau mise � jour.

    J'ai d�j� impl�ment� quelque chose de ce style l�, mais j'aimerais l'optimiser. J'ai donc fait quelques tests :

    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
    // super lent
    std::unordered_map<int,int> map = {{0,1},{1,8},{2,4},{3,6},{4,2},{5,8},{6,5},{7,4},{8,0},{9,1},{10,6},{11,3},{12,8},{13,4},{14,6}};
    std::vector<int*> vector2;
    for (int i=0; i<15; i++)
     vector2.push_back(&map[i]);
    sf::Clock c;
    for (int i=0; i<1000; i++)
     for (int j=0; j<15; j++)
      (*vector2[j])++;
    std::cout<<c.getElapsedTime().asMicroseconds();
     
    // rapide
    std::vector<int> vector1 = {1,8,4,6,2,8,5,4,0,1,6,3,8,4,6};
    std::vector<int*> vector2;
    for (int i=0; i<15; i++)
     vector2.push_back(&vector1[i]);
    sf::Clock c;
    for (int i=0; i<1000; i++)
     for (int j=0; j<15; j++)
      (*vector2[j])++;
    std::cout<<c.getElapsedTime().asMicroseconds();
    J'en ai donc d�duit qu'il serait plus int�ressant de stocker tous les components dans un seul vector, et de faire pointer les components des entit�s sur les �l�ments de ce vector. �a donnerait :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    vector<Component*> components; // tous les components, vraiment tous, c'est ici qu'on fait les new
    map<int,map<std::type_index,Component*>> entities. // les entités, on ne fait plus les new ici, on fait pointer sur components[x]
    vector<Component*> system; // pareil, ici, on fait aussi pointer sur components[x]
    Mon probl�me, c'est que �a commence � devenir un v�ritable bordel si on veut supprimer un component d'une entity, et j'aurais voulu rendre �a beaucoup plus simple en stockant directement dans chaque component sa position dans les systems (c'est l'exemple de mon premier post) et aussi dans entities. Mon exemple n'�tait peut �tre pas super clean, mais l'id�e �tait l�.

    M�me en utilisant les shared_ptr, �a ne r�soudrait pas mon probl�me, � savoir supprimer les �l�ments des containers.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    vector<shared_ptr<Component>> components; // on peut éventuellement s'en passer
    map<int,map<std::type_index,shared_ptr<Component>> entities;
    vector<shared_ptr<Component>> system;

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Citation Envoy� par koala01 Voir le message
    Mais de l� � dire que ce comptage de r�f�rence occasionne une telle perte, il y a de la marge : le comptage de r�f�rence est une op�ration � priori atomique, ce qui implique qu'il devrait s'effectuer en un temps minimum
    Attention l� il y a un pi�ge. Une op�ration sur un entier atomique (si l'architecture en dispose et on peut le v�rifier avec atomic_is_lock_free) ne s'effectue pas "en un temp minimum". Les atomiques c'est bien mais �a a un co�t : �a implique de synchroniser les caches entre les diff�rents coeurs du processeur, ce n'est pas anodin du tout. C'est beaucoup plus cher que la m�me op�ration sur un entier non-atomique. Mal utilis�, �a peut carr�ment pourrir des perfos, m�me si �a les pourrira moins qu'un mutex qui r�alise la m�me op�ration.

    Encore une fois, ce sont les mesures qui doivent le d�terminer. Mais il ne faut pas partir du principe que parce c'est atomique, l'impact est faible. Ca d�pend.

    Citation Envoy� par MrPchoun Voir le message
    Mon probl�me, c'est que �a commence � devenir un v�ritable bordel si on veut supprimer un component d'une entity, et j'aurais voulu rendre �a beaucoup plus simple en stockant directement dans chaque component sa position dans les systems (c'est l'exemple de mon premier post) et aussi dans entities. Mon exemple n'�tait peut �tre pas super clean, mais l'id�e �tait l�.

    M�me en utilisant les shared_ptr, �a ne r�soudrait pas mon probl�me, � savoir supprimer les �l�ments des containers.
    H�las en effet ! J'ai eu exactement le m�me probl�me, et je l'ai r�gl� d'une mani�re assez peu catholique. L'id�e, en gros est d'avoir des weak_ptr vers les components, et de ne stocker qu'un seul shared_ptr dans le propri�taire. C'est dommage car concr�tement on n'a pas besoin de propri�t� partag�e, mais on a besoin de pouvoir savoir si l'objet est encore en vie ou pas, et en standard seul weak_ptr sait faire cela. Au moment de faire ta passe d'update, tu en profites pour noter les r�f�rences qui pointent vers des objets d�truits et nettoyer le vector � la fin. Ca marche bien parce que tu sais que tu vas souvent faire des update, et donc que ce sera r�guli�rement nettoy�. Dans la pratique, je n'ai pas utilis� la lib standard et j'ai impl�ment� moi m�me une version de weak_ptr non thread safe, parce que j'avais qu'un seul thread et que je voulais pas payer l'atomicit�, du coup c'est assez efficace. A toi de voir dans ton cas comment tu pourrais exploiter �a, tout d�pend si tes suppressions sont fr�quentes ou pas, comment tu multi-thread, etc.

    En tout cas, ce n'est pas �vident, et �a reste une affaire de compromis, nettoyer chaque collection qui a une r�f�rence vers ton composant aura un co�t. Tu peux le payer � la suppression du composant, ou le payer plus tard lors d'une autre op�ration, mais la facture tombera. A mon avis, tu peux exploiter le fait que chaque syst�me ne r�f�rence qu'un type de composant donn�, je connais pas assez bien ton projet pour savoir .

  11. #11
    Membre �clair�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : Sant�

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par d�faut
    Citation Envoy� par MrPchoun Voir le message
    J'avais fait des mesures, oui. Apr�s, le chiffre de 10 �tait peut �tre un peu gros, mais je me souviens de quelque chose d'assez �norme, qui m'a rebut� direct, pour �a que j'ai mis de c�t� la m�thode smart pointer.
    Je viens de faire un petit exemple pour comparer les r�sultats. C'est vrai que les shared_ptr sont un peu plus co�teux que les pointeurs nus mais ce n'est une diff�rence �norme non plus. J'ai lancer le code suivant quelques fois pour faire ces comparaisons:
    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
    51
    52
    53
    54
    55
    56
    #include <iostream>
    #include <chrono>
    #include <vector>
    #include <memory>
    #include <stdint.h>
     
    void rawPointers(size_t nbElements)
    {
        std::vector<uint32_t*> vect;
        vect.resize(nbElements);
        for (size_t i = 0; i < nbElements; ++i)
        {
            vect.push_back(new uint32_t(i));
        }
     
        for (size_t i = 0; i < nbElements; ++i)
        {
            delete vect[i];
        }
    }
     
    void sharedPointers(size_t nbElements)
    {
        std::vector<std::shared_ptr<uint32_t>> vect;
        vect.resize(nbElements);
        for (size_t i = 0; i < nbElements; ++i)
        {
            vect.push_back(std::make_shared<uint32_t>(uint32_t(i)));
        }
    }
     
    int main()
    {
       std::chrono::system_clock::time_point start;
       std::chrono::system_clock::time_point end;
     
       size_t nbElements = 1000000;
     
       start = std::chrono::system_clock::now();
       sharedPointers(nbElements);
       end = std::chrono::system_clock::now();
     
       std::cout << "Shared pointers - Elapsed Time: " <<  
                 std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
     
     
       start = std::chrono::system_clock::now();
       rawPointers(nbElements);
       end = std::chrono::system_clock::now();
     
       std::cout << "Raw pointers - Elapsed Time: " <<  
                 std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
     
     
       return 0;
    }
    J'obtiens les r�sultats suivant:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Shared Pointer Time (us)	 Raw Pointer Time (us)
    190078	139325
    196413	145892
    207095	152433
    183025	148365
    193554	137738
    177309	127623
     
    191245.6667	141896
    134.78%	100.00%

    Sinon pour ton probl�me principal, je ne pense pas que le probl�me vienne des pointeurs nus ou des pointeurs intelligents mais de l'utilisation de std::map � l'int�rieur d'une std::map. L'acc�s aux �l�ments d'une map est en log(N) si je ne me trompe pas, c'est � dire que c'est relativement lent pour chaque acc�s.

    Je ne sais pas combien tu as de sortes de Component mais si ils sont peux nombreux et que tu dois activer d�sactiver r�guli�rement ceux-ci au niveau d'une entit�, ne serait-il pas judicieux d'avoir pour chaque entit� un tableau fixe de composant dont chaque case du tableau correspond � un composant particulier. Le probl�me de cette solution, c'est que tu dois faire un test � chaque fois pour savoir si le composant est utilis� ou non.
    Voici un petit exemple:

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    class Component
    {
    public:
       //tous les constructeurs etc
     
       virtual void update() = 0;
    };
     
    class ScoreComponent : public Component
    {
    public:
      static unsigned int id() const
      {
         return 0;
      }
      virtual void update()
      {
        //Quelque chose
      }
    };
     
     
    class InventoryComponent : public Component
    {
    public:
      static unsigned int id() const
      {
          return 1;
      }
     
      virtual void update()
      {
        //Quelque chose
      }
    };
     
    class Entity
    {
    private:
      std::vector<Component*> m_components;
     
    public:
      Entity()
      {
         m_components.resize(2); //Le nombre de composants (tu peux faire un truc moins static en enregistrant les composants dans une factory par exemple) 
      }
     
      void attach(unsigned int id, Component * component)
      {
         m_components[id] = component;
      }
     
      void detach(unsigned int id)
      {
         m_components[id] = 0;
      }
     
      void update()
      {
         for (Components * comp : m_components)
         {
             if (comp)
             {
                 comp->update();
             }
         }
      }
    };
     
    int main()
    {
       ScoreComponent * score = new ScoreComponent();
       InventoryComponent * inventory = new InventoryComponent();
     
       Entity e;
       e.attach(ScoreComponent::id(), score);
       e.attach(InventoryComponent::id(), inventory); 
     
       e.detach(ScoreComponent::id());
       e.detach(InventoryComponent::id());
     
       delete score;
       delete inventory;
     
       return 0;
    }

  12. #12
    Membre confirm�
    Homme Profil pro
    D�veloppeur du dimanche
    Inscrit en
    F�vrier 2013
    Messages
    154
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur du dimanche

    Informations forums :
    Inscription : F�vrier 2013
    Messages : 154
    Par d�faut
    @jblecanard

    Pas b�te, la m�thode shared_ptr + weak_ptr, j'avais pas pens� � �a, �a peut toujours me d�lester des delete. Je vais approfondir �a Par contre, clean les vector � chaque boucle, �a me branche vraiment pas.. Le but c'est vraiment de gagner le max de temps dans le systems, quitte � en perdre un peu dans les ajouts/suppressions de Component, parce que les ajouts/suppressions ne se font pas � chaque boucle. Par contre les sytems, eux, tournent � chaque boucle

    @darkman19320

    je ne pense pas que le probl�me vienne des pointeurs nus ou des pointeurs intelligents mais de l'utilisation de std::map � l'int�rieur d'une std::map
    � vrai dire dans l'impl�mentation de mon ECS j'utilise des std::unordered_map, mais �a change pas grand chose en fait, puisque comme mes systems stockent des pointeurs sur Component, j'ai pas le temps d'acc�s � me farcir � chaque boucle. Je comprends ton exemple (par contre, o� sont les systems ? Jamais d'update dans les Components, c'est mal ) mais pourquoi faire un vector � taille fixe et pas d�clarer directement un Component*[2] ? L'acc�s en [x] est constant, alors qu'il ne l'est pas sur un vector..

    �a pourrait �tre pas mal comme id�e, mais je sais pas comment �a va se passer au niveau des perfs en fait. Parce que je serai quand m�me oblig� de stocker mes Entity dans une unordered_map, pour avoir un acc�s constant � une Entity. Au del� de �a, quand je mets tous mes Components dans un seul vector, j'ai l'impression que �a soulage un peu le systems. Si je fais un truc style unordered_map<vector<Component*>> �a risque de plomber le cache, m�me si mon vector de Component stockaient des new, ce qui fait que c'�tait pas align� en m�moire, j'ai l'impressions que les perfs �taient pas trop d�geux.

    En plus, stocker des Component vides dans un tableau, �a m'emb�te un peu, �a gave la RAM pour rien, imagine que j'ai une vingtaine de Component (Position, Sant�, Sprite, Mouvement, �a va vite..)

    Bref, �ternel choix corn�lien entre programme rapide/programme lourd !

    Je vais adapter un peu ton code � ma sauce, je verrai bien !

    Merci de vos r�ponses

  13. #13
    Membre �clair�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : Sant�

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par d�faut
    Citation Envoy� par MrPchoun Voir le message
    L'acc�s en [x] est constant, alors qu'il ne l'est pas sur un vector..
    Si si l'acc�s aux �l�ments � un vector est constant.

    Sinon c'est vrai que je n'ai pas ajout� les System, je ne connais pas trop ce pattern du coup, j'ai fait au plus simple ^^

    Citation Envoy� par MrPchoun Voir le message
    En plus, stocker des Component vides dans un tableau, �a m'emb�te un peu, �a gave la RAM pour rien, imagine que j'ai une vingtaine de Component (Position, Sant�, Sprite, Mouvement, �a va vite..).
    Tu ne stockes pas les Component mais des pointeurs sur des Components. Donc dans le pire des cas, dans ton tableaux tu auras une vingtaine de pointeurs donc de taille fixe. Mais je comprends ton point de vue.

    Citation Envoy� par MrPchoun Voir le message
    Bref, �ternel choix corn�lien entre programme rapide/programme lourd!
    Exactement, toujours le m�me probl�me. Bon courage!

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. R�ponses: 6
    Dernier message: 04/08/2013, 20h56
  2. R�ponses: 7
    Dernier message: 10/03/2007, 11h08
  3. probleme de delete dans un destructeur
    Par Chewbi dans le forum C++
    R�ponses: 6
    Dernier message: 12/03/2006, 00h29
  4. erase et delete d'un vector
    Par Jahjouh dans le forum SL & STL
    R�ponses: 3
    Dernier message: 30/11/2005, 23h11
  5. destructeur et vector
    Par diefo dans le forum SL & STL
    R�ponses: 14
    Dernier message: 02/03/2005, 12h15

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