2010-04-16 5 views
6

J'essaie d'utiliser un conteneur Boost MultiIndex dans ma simulation. Ma connaissance de la syntaxe C++ est très faible, et je crains de ne pas supprimer correctement un élément du conteneur ou de le supprimer de la mémoire. J'ai aussi besoin de modifier les éléments, et j'espérais confirmer la syntaxe et la philosophie de base ici aussi.Effacement et modification d'éléments dans Boost MultiIndex Container

// main.cpp 
... 
#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/hashed_index.hpp> 
#include <boost/multi_index/member.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index/mem_fun.hpp> 
#include <boost/tokenizer.hpp> 
#include <boost/shared_ptr.hpp> 
... 
#include "Host.h" // class Host, all members private, using get fxns to access 

using boost::multi_index_container; 
using namespace boost::multi_index; 

typedef multi_index_container< 
    boost::shared_ptr<Host>, 
    indexed_by< 
    hashed_unique< const_mem_fun<Host,int,&Host::getID> > 
    // ordered_non_unique< BOOST_MULTI_INDEX_MEM_FUN(Host,int,&Host::getAge) > 
    > // end indexed_by 
    > HostContainer; 

typedef HostContainer::nth_index<0>::type HostsByID; 

int main() { 
    ... 
    HostContainer allHosts; 
    Host * newHostPtr; 
    newHostPtr = new Host(t, DOB, idCtr, 0, currentEvents); 
    allHosts.insert(boost::shared_ptr<Host>(newHostPtr)); 
    // allHosts gets filled up 

    int randomHostID = 4; 
    int newAge = 50; 
    modifyHost(randomHostID, allHosts, newAge); 
    killHost(randomHostID, allHosts); 
} 

void killHost(int id, HostContainer & hmap){ 
    HostsByID::iterator it = hmap.find(id); 
    cout << "Found host id " << (*it)->getID() << "Attempting to kill. hmap.size() before is " << hmap.size() << " and "; 
    hmap.erase(it); // Is this really erasing (freeing from mem) the underlying Host object? 
    cout << hmap.size() << " after." << endl; 
} 

void modifyHost(int id, HostContainer & hmap, int newAge){ 
    HostsByID::iterator it = hmap.find(id); 
    (*it) -> setAge(newAge); // Not actually the "modify" function for MultiIndex... 
} 

Mes questions sont

  1. Dans le conteneur multiindice allHosts de shared_ptrs à Host objets, appelle allHosts.erase(it) sur un itérateur suffisant pour supprimer l'objet de façon permanente et la libérer de la mémoire de shared_ptr de l'objet? Il semble supprimer le shared_ptr du conteneur.
  2. Le conteneur allhosts possède actuellement un index de fonctionnement qui repose sur l'ID de l'hôte. Si j'introduis un second index ordonné qui appelle une fonction membre (Host :: getAge()), où l'âge change au cours de la simulation, l'index sera-t-il toujours mis à jour quand je le ferai?
  3. Quelle est la différence entre l'utilisation de la modification de MultiIndex pour modifier l'âge de l'objet sous-jacent par rapport à l'approche que je montre ci-dessus?
  4. Je suis vaguement confus au sujet de ce qui est supposé/doit être constant dans MultiIndex.

Merci à l'avance.


Mise à jour

Voilà ma tentative pour obtenir le travail de syntaxe modify, basée sur ce que je vois dans un coup de pouce example connexe.

struct update_age { 
    update_age():(){} // have no idea what this really does... elicits error 
    void operator() (boost::shared_ptr<Host> ptr) { 
    ptr->incrementAge(); // incrementAge() is a member function of class Host 
    } 
}; 

puis à modifyHost, j'aurais hmap.modify(it,update_age). Même si, par miracle, cela s'avère juste, j'adorerais avoir une explication de ce qui se passe.

Répondre

7

shared_ptr va supprimer l'objet réel Host dans son destructeur (s'il n'y a pas d'autres instances de shared_ptr). Tous les objets de MultiIndex sont considérés comme constants. Pour modifier l'objet, vous devez utiliser la méthode modify de MultiIndex. Dans ce cas, les index seront mis à jour si nécessaire.

Vous pouvez utiliser le foncteur suivante pour changer age champ:

struct change_age 
    { 
    change_age(int age) : age_(age) {}  
    void operator()(boost::shared_ptr<Host> h) // shared_ptr !!! 
    { 
     h->age = age_; 
    } 

    private: 
    int age_; 
    }; 

utiliser ensuite comme suit:

testHosts.modify(it, Host::change_age(22)); // set age to 22 
+0

Merci encore. Même après avoir étudié votre lien, j'ai toujours des problèmes avec la syntaxe de modification. L'utilisation de hmap.modify (it, incrementAge()), avec Host :: incrementAge(), provoque une erreur hors champ. Je vois quelques exemples utilisant des structures (quand les éléments du conteneur sont les objets eux-mêmes) mais ne peuvent pas suivre pourquoi mon code ne fonctionne pas. – Sarah

+0

Mise à jour de ma réponse pour montrer comment utiliser 'modify'. –

+0

Merci, Kirill - c'est très utile. (J'ai d'autres fonctions membres qui prennent des entrées, et que j'aurai besoin d'invoquer avec modify().) Je ne comprends toujours pas ce que je dois faire quand j'essaye d'appeler une fonction membre qui ne prend pas d'entrées, cependant - mon code édité ci-dessus est-il correct? – Sarah