2013-04-11 4 views
1

J'ai des objets de type MyClass stockés en tant que paires <std::string, MyClass> dans une carte STL. La chaîne std :: string est un nom unique pour chaque objet MyClass. Je veux que chaque objet MyClass soit instancié seulement une fois par nom et ainsi détruit seulement une fois à la fin dans mon application. J'essaie donc d'éviter l'invocation de constructeurs de copie ou de constructeurs par défaut, car ils pourraient invoquer la destruction. Un objet MyClass fait référence à une sorte de ressource qui doit être allouée/libérée une seule fois. J'ai essayé d'utiliser ce code pour créer des instances de MyClass, les mettre dans ma map et donner un pointeur vers l'instance nouvellement créée.Constructeur de copie d'insertion de carte STL

MyClass* FooClass::GetItem(std::string name) 
{ 
    MyClass* item = GetItemExists(name); 

    if (item == NULL) 
    { 
     item = &(*((this->myMap.insert(std::pair<std::string, MyClass> 
             (name, MyClass(name)))).first)).second;  
    } 

    return item; 
} 

La création et l'insertion fonctionnent de cette manière. Mais le destructeur de Class MyClass s'appelle 3! fois. Même l'instruction return item; invoque le destructeur, car il s'agit d'un pointeur ?! Je pensais que c'est impossible et doit être forcé par delete item?!

Je pensais qu'une alternative est de stocker des pointeurs MyClass * au lieu d'objets dans la carte. Ou y a-t-il une meilleure alternative? Je n'ai pas utilisé myMap[name] = MyClass(name); pour éviter la copie/destruction, mais je pense que l'insertion ne le rend pas meilleur.

+0

sonne comme une bonne utilisation pour '' shared_ptr . Mettez cela dans votre carte au lieu de 'MyClass'. Un pointeur partagé ne copiera pas vos objets MyClass et détruira chacun d'entre eux lorsqu'il n'est plus utilisé. – john

+0

Vous pouvez également dériver 'MyClass' de' boost :: noncopyable' pour empêcher la copie de la protection. – tehlexx

+0

Ok thx, shared_ptr et boost :: nononcopyable sont de bons indices, je vais l'utiliser. – Michbeckable

Répondre

1

Vous devez emplace et construire l'élément piecewise inséré:

item = &(this->myMap.emplace(std::piecewise_construct, 
          std::forward_as_tuple(name), 
          std::forward_as_tuple(name)).first->second); 
+0

Etes-vous sûr que la deuxième partie est correcte? Est-ce que emplace ne retourne pas un 'std :: pair '? – inf

+0

@bamboon oups, oubli, la chose '.first-> second', merci. – ecatmur

+0

Je n'ai jamais vu ça avant, je vais l'essayer, merci. Pouvez-vous expliquer pourquoi l'instruction insert invoque souvent constructor/destructor et pourquoi est-elle même invoquée à l'item return, bien que ce soit un pointeur ici? – Michbeckable