2016-05-21 5 views
1

Lagerung von Monstern:Intelligente Zeiger und die Abhängigkeit von ihm in dem gesamten Programm, einmal benutzten

class MonstersStorage 
{ 
    public: 
    std::weak_ptr<Monster> getMonster(int ID) const; 
    private: 
    std::vector<std::shared_ptr<Monster>> monsters; 
} 

Es gibt nur eine Speicherung von Monstern im Spiel. Es gibt eine Menge Code, der Monster Objekte verwendet.

Ich habe den Speicher von Monstern gemacht, der nur aus einem Grund intelligente Zeiger speichert - manchmal muss man an anderer Stelle auf Monster verweisen und Monster können sterben (gelöscht werden und aus dem Speicher entfernt werden) - also müssen die Referenzen sicher ablaufen . Ansonsten würde ich nur normale Zeiger verwenden.

Problem ist, dass im ganzen Spiel, an jedem Ort, dass Monster verwendet wird, muss es schwache Zeiger anstelle von einfachen Verweis oder Zeiger sein - weil alle Monster Objekte aus einer Quelle kommt - Monster Storage.

Selbst im Fall von Funktionen, die nur Monster benötigen, um an sie übergeben zu werden, und einige Operationen ausführen, aber keine Referenz darauf speichern. Zum Beispiel:

getDamageDealedBy(const Monster&); 

Es wird sein müssen:

getDamageDealedBy(const std::weak_ptr<Monster>&); 

Es wird die gesamten Code je nach Monster Lagerung Umsetzung.

Meine Frage ist, bei solchen Funktionen soll ich nur einfache Referenzen, von * .get empfangen() von Smart-Pointer, Oder sollte weak_ptr im gesamten Programm bei Monster Klasse verwendet werden.

Editiert: Und immer diese .lock verwenden() -Funktionen über, und immer wieder, sie zu konvertieren, Shared_ptr während Monster Zugriff auf

Antwort

2

Es gibt nur Person, die die Antwort auf diese Frage hat. Dies ist die Person, die genau den Umfang und die Lebensdauer jedes Objekts kennt, das den Smartpointern gehört. Das wärst du.

Wenn der letzte std::shared_ptr, der sich auf ein bestimmtes Objekt bezieht, den Gültigkeitsbereich verlässt, wird das Objekt zerstört. Wenn, basierend auf der Art, wie Ihre Anwendung diese Objekte verwendet, dies niemals passieren kann, während ein anderer Teil Ihrer Anwendung einen normalen "nicht-intelligenten" Zeiger verwendet, um auf dieses Objekt zu verweisen, dann ist es natürlich nur normal Zeiger.

Zum Beispiel, hier ist eine Situation, die Sie wissen, dass es sicher wäre, einen gewöhnlichen Zeiger zu verwenden.

void somefunction(const std::shared_ptr<Monster> &monster_ptr) 
{ 
    Monster *p=monster_ptr.get(); 

    // ... Use p inside this function 
} 

Da die std::shared_ptr-somefunction() als Parameter übergeben wird, und der Umfang der monster_ptr existiert für den gesamten somefunction() es sicher ist nur get() verwenden und den zurückgegebenen Zeiger in dieser Funktion verwenden.

Sie wissen, dass monster_ptr für die Dauer dieser Funktion existiert. Daher behält monster_ptr einen std::shared_ptr Verweis auf das zugrunde liegende Objekt, und deshalb wird immer mindestens eine intelligente Referenz auf das zugrunde liegende Objekt für die Dauer dieser Funktion (und für die Dauer jeder anderen Funktion, die von diesem aufgerufen wird) Funktion).monster_ptr wird erst nach somefunction() zurückgegeben, und bis das passiert ist, wird garantiert, dass Sie eine intelligente Referenz auf das zugrunde liegende Objekt haben, und es ist sicher, einen direkten nativen Zeiger zu verwenden.

Fazit: Wenn Sie beweisen können, dass an einem bestimmten Punkt in Ihrer Anwendung ist es garantiert, dass es mindestens eine std::shared_ptr Verweis auf ein bestimmtes Objekt, dann ist es sicher, einen gewöhnlichen Zeiger auf dieses Objekt zugreifen.