Ich habe einen Ressourcenmanager, der Ressourcen lädt und zurückgibt. Derzeit kehre ich nur shared_ptrs
für die von mir erstellten Ressourcen zurück, denke aber darüber nach, so etwas wie einfache Handles zu verwenden, wobei Sie eine ID erhalten, mit der Sie auf die Ressource zugreifen. Die Gründe sind expliziteres Eigentum und auch weniger Overhead als Verwendung smart_ptrs
.
Sind Ressourcenhandles der effizienteste Weg, um auf Ressourcen zuzugreifen, sollte ich mich an shared_ptrs halten oder gibt es andere Alternativen?
Der Grund , den ich frage , ist, dass ich diesen Artikel gelesen habe , was mich gefragt hat, ob ich stattdessen so etwas implementieren soll.
c++
resource-management
KaiserJohaan
quelle
quelle
Antworten:
Ich bin mit Vittorio nicht einverstanden, dass kein gemeinsames Eigentum an Ressourcen erforderlich ist, und obwohl ich die Implementierung von nicht mag
shared_ptr
, kann sie gut funktionieren.Sie möchten eine gemeinsame Eigentümerschaft, da natürlich möglicherweise mehrere Spielobjekte dieselbe Ressource verwenden. Noch wichtiger ist, dass Sie, wenn Sie mehrere Ebenen haben und die Ebenen mindestens laden möchten, eine Möglichkeit benötigen, die Vereinigung und Schnittmenge der von beiden benötigten Ressourcen zu berechnen.
Eine Möglichkeit, dies zu tun, die mehr als nur ein erfordert
shared_ptr
, besteht darin, das "Laden" eines Levels ohne Ressourcen zu ermöglichen und es das gemeinsame Eigentum an den benötigten Ressourcen übernehmen zu lassen. Entladen Sie dann das alte Level und entfernen Sie dessen Besitz. Laden Sie dann für jede Ressource, deren Eigentümer noch aktiv ist, die jedoch nicht geladen ist, die Ressource.Für eine Ressource A, die von Level 1 und 2 benötigt wird, lautet der Referenzzähler ungefähr wie folgt:
Für eine Ressource B, die nur von Stufe 1 verwendet wird, gilt Folgendes:
Und eine Ressource C, die nur von Stufe 2 verwendet wird, sieht folgendermaßen aus:
Eine Methode könnte darin bestehen, eine Indirektionsebene zu haben. Sie speichern
shared_ptr
in einemResourceHolder
. Diese Inhaber sind auch in einer Liste irgendeiner Art. Beim Laden eines Levels erstellen Sie dieseResourceHolder
Objekte und halten sie fest . Sie enthalten aunique_ptr
zur eigentlichen Ressource (anfangsnullptr
) und den Pfad oder andere Informationen, die zum eventuellen Laden des Elements erforderlich sind.Nachdem Sie die neue Ebene geladen und die alte entladen haben, können Sie die Liste der Live-
ResourceHolder
Objekte durchlaufen, nach Objekten suchen, die einnullptr
Handle für die eigentliche Ressource haben, und diese dann laden. Wenn dasshared_ptr
to aResourceHolder
eine Ref-Anzahl von 0 erreicht und es entlädt, gibt es natürlich auch die Ressource frei, und Sie sollten sicherstellen, dass es sich selbst aus der Liste der Live-Ressourcen entfernt.Sie können es viel besser machen als,
shared_ptr
aber es ist ein perfekter Ort, um loszulegen. Optimieren Sie es später zu etwas Besserem, sobald Sie ein funktionierendes Spiel haben.quelle
shared_ptr
und sogar von GC im Allgemeinen entwickelt, obwohl ich in der Vergangenheit in Teams gearbeitet habe, in denen beide als Ausreden angesehen wurden, um nicht über Ressourcenmanagement und Eigenverantwortung nachzudenken. Das Ergebnis war sehr logisch Lecks, bei denen der analoge Absturz des baumelnden Zeigers zu einem stillen Speicherverlust wurde, der unter dem Radar des Testens flog, da eine Ressource einen shared_ptr für einen anderen speichern würde, dessen Lebensdauer lange hätte beendet werden müssen [...]shared_ptr
. Seitdem zögere ich nicht mehr mit shared_ptrs und sogar mit GC, mit all den schwer zu erkennenden Lecks, auf die ich gestoßen bin.Nein, sie sind nicht die effizienteste Möglichkeit, auf Ressourcen zuzugreifen. Der gleiche Sean Middleditch, der Ihnen eine Antwort gegeben hat, schrieb einen Artikel " Gefahren von std :: shared_ptr " gegen die Verwendung
shared_ptr
etwa ein Jahr später. Möglicherweise möchten Sie erneut Handles verwenden. Wie er selbst schrieb:Weitere Informationen dazu, wie Sie bei der Verwendung von Griffen im Gegensatz zu viel effizienter arbeiten können, finden Sie im Abschnitt Effizienz in seinem Artikel
shared_ptr
.Weitere Vorteile von IDs finden Sie im kurzen Artikel zum Entity Component System Pattern .
quelle