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::vector : Suppression pendant une iteration


Sujet :

C++

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut std::vector : Suppression pendant une iteration
    Bonjour à tous,


    Pour implémenter le pattern Observer, je propose une interface d'écoute.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class IListener
    {
    public:
       virtual void OnEvt();
    }
    Ensuite, dans la classe pouvant lancer cet évennement, j'ai un vector d'objets implémentant cette interface, et je propose de s'inscrire ou se désinscrire à cet evennement.

    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 MaClass
    {
    public:
       void AddListener(IListener* pListener);
       void RemoveListener(IListener* pListener);
     
    private:
       void NotifyEvt();
       std::vector<IListener*> m_vecListeners;
    }
     
    void MaClass::NotifyEvt()
    {
       for(std::vector<IListener*>::iterator it = m_vecListeners.begin(); it != m_vecListeners.end(); ++it)
       {
          (*it)->OnEvt();
       }
    }
    Mon soucis est que sur réception de l'évennement, certains écouteurs peuvent ne plus avoir besoin d'écouter. Donc ils font
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_maClass.RemoveListener(this);
    Ce qui provoque la suppression d'un élément dans le vector alors que je suis en train d'iterrer dessus.

    J'ai essayer de mettre un iterator en tant que membre de ma classe, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private:
       std::vector<IListener*> m_vecListeners;
       std::vector<IListener*>::iterator m_CurIt;
    Puis de l'initialiser à begin() en début de notification, et, lors du "erase" sur le vector, de lui affecter le retour.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_CurIt = m_vecListeners.erase(std::find(m_vecListeners.begin(), m_vecListeners.end(), pListener));
    Mais dans la boucle de notification, si m_CurIt a été réaffecté (donc à l'élément suivant), il ne faut pas que je l'incrémente, sinon je l'incrémente, mais il faut également gérer le cas où il est passé à m_vecListeners.end() etc...

    Bref, j'arrive à quelque chose d'étrangement compliqué et je voudrai savoir s'il n'y avait pas un moyen plus simple pour gérer ce genre de chose ?

    Merci beaucoup,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    J'avais résolu ce genre de problème avec les pointeurs intelligents.
    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
     
    class MaClass
    {
    public:
       void AddListener(boost::shared_ptr<IListener> pListener);
       void RemoveListener(boost::shared_ptr<IListener> pListener);
     
    private:
       void NotifyEvt();
       std::vector<boost::weak_ptr<IListener> > m_vecListeners;
    }
     
    void MaClass::NotifyEvt()
    {
       for(boost::weak_ptr<IListener>::iterator it = m_vecListeners.begin(); it != m_vecListeners.end(); )
       {
          boost::shared_ptr<IListener> ptr = it->lock();
          if (ptr)
          {
               ptr->NotifyEvt();
               it++;
          }
          else {
               it = m_vectListeners.erase(it);
          }
       }
    }
    En stockant des weak_ptr, tu n'es pas responsable de leur cycle de vie. Celà suppose que tu gères tes ressources avec des pointeurs intelligents pour le reste. Moi c'est toujours le cas, donc !
    Du coup, tes ressources sont toujours libérées via shared_ptr, et ton vector d'observateur est mis à jour tout seul si la ressource n'existe plus!

  3. #3
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Tu peux aussi copier le vecteur et itérer sur la copie.

    MAT.

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Ha bah oui, pas bête, j'vais essayer ça tien.

    Merci
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

Discussions similaires

  1. Pb std::vector dans une classe
    Par didi_di dans le forum Langage
    Réponses: 8
    Dernier message: 17/11/2009, 10h07
  2. Suppression dans un std::vector
    Par bobo034 dans le forum SL & STL
    Réponses: 1
    Dernier message: 18/07/2008, 16h16
  3. Réponses: 10
    Dernier message: 30/06/2008, 19h59
  4. Retourner une référence sur un std::vector
    Par Rodrigue dans le forum C++
    Réponses: 12
    Dernier message: 13/10/2007, 16h30
  5. [LG]suppression dans une liste chainée
    Par mister_dsg dans le forum Langage
    Réponses: 9
    Dernier message: 16/12/2003, 21h20

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