Halten Sie statt roher Zeiger einen anderen einfachen Verweis auf die Ressource. A shared_ptr
und entsprechende weak_ptr
Instanzen sind ein solcher Mechanismus, aber Sie können Ihren eigenen einfach implementieren, wenn Sie keinen Zugriff auf diese Typen (oder ihre früheren Boost-Äquivalente) haben oder wenn es andere Gründe gibt, warum diese Typen für Ihr Szenario nicht geeignet wären (z als zu schwer).
Diese Art von 'Handle'-System kann so einfach sein wie das Verteilen von Ganzzahlen, die sich auf interne Slots im Ressourcensystem beziehen. Diese können dann verwendet werden, um eine Ressource dynamisch neu zu laden, wenn während des Entladens Zugriff darauf angefordert wird.
In der Praxis möchten Sie wahrscheinlich etwas Robusteres, zumindest eine Möglichkeit, das Handle "wie" einen Zeiger zu behandeln und operator ->
Überladungen bereitzustellen , indem Sie es beispielsweise in einen Handle
Typ einschließen . Dieser
Handle
Typ kann nur einen Zeiger auf einen im Ressourcenmanager gespeicherten "Steuerblock" enthalten. Der Steuerblock enthält die Rohressourcenreferenz und ein boolesches Flag, das angibt, ob die Ressource aktiv ist oder nicht, sowie eine Art Schlüssel, mit dem die Ressource bei Bedarf neu geladen werden kann (im folgenden Beispiel wird eine Zeichenfolge angenommen). Ein sehr einfaches Beispiel hierfür könnte folgendermaßen aussehen:
template <typename Resource>
struct Handle {
Resource * operator -> () }
return m_owner->retrieve_resource(m_resource_id);
}
private:
int m_resource_id;
resource_manager * m_owner;
};
namespace detail {
struct control_block {
Resource * resource;
bool is_alive;
std::string key;
};
};
struct resource_manager {
Resource * retrieve_resource (int id) {
auto block = m_resources[id];
if (block->is_alive) {
return block->resource;
} else {
block->resource = reload_resource(key);
block->is_alive = true;
return block->resource;
}
}
private:
std::vector<detail::control_block> m_resources;
};
In dieser Implementierung speichert der Ressourcenmanager nur ein flaches Array von Steuerblöcken, auf die durch eine Ganzzahl verwiesen werden kann, und bietet eine Methode zum Wiederherstellen eines Ressourcenzeigers anhand der ID, wobei diese Ressource bei Bedarf neu geladen wird. Die Handle
Klasse ist nur ein nützlicher Wrapper für dieses Verhalten. Offensichtlich ist dies jedoch ein sehr einfaches Beispiel. Wenn Sie etwas vollständigeres wünschen, lesen Sie den Artikel von Scott Bilas über einen generischen handle-basierten Ressourcenmanager . Es geht etwas anders vor, ist aber die Lektüre wert.
(Seien Sie gewarnt, dass ein Bedarf, den Ihre Frage impliziert, bedeuten kann, dass Ihre Ressourcennutzung sehr chaotisch ist, und das ist nicht unbedingt eine gute Sache für die Leistung, daher sollten Sie dies in Betracht ziehen.)
shared_ptr
). Es hat alle Fehler der automatischen GC in Bezug auf die Semantik und alle Nachteile der Referenzzählung in Bezug auf die Implementierung.shared_ptr
intelligente Zeiger tendenziell mehr Kopfschmerzen verursachen, als sie wert sind. Eine Menge von sehr schwer zu debuggen Problemen kann auftauchen Nähe des Versands beginnen , die alle laufen auf Referenz Lecks (aber kein Clearingshared_ptr
wenn Sie sollen) oder Destruktoren zur falschen Zeit aufgerufen werden (Objekte am Leben zu lange bleiben dann bei einer Zerstörung schlechte Zeit).