Wenn ich Direct3D in C ++ benutze, kann ich zum Beispiel eine "Cube" -Klasse schreiben, die einen "ID3D11Buffer * vertexBuffer_" enthält und sicherstellen, dass der Destruktor für dieses Cube-Objekt vertexBuffer _- & gt; Release () aufruft.
Ich kann eine "Scene" -Klasse haben, die ein "unique_ptr cube_" -Objekt enthält. Damit ich weiß, dass der Würfel gelöscht wird, wenn ich meine Szene lösche, und das wird folglich Release auf den D3D-Ressourcen aufrufen, die es verwendet.
In D kann ich das nicht machen. Ich kann Destruktoren schreiben, aber ich habe keine Ahnung, wann sie angerufen werden. Wenn der GC den Speicher nicht benötigt, darf er niemals aufgerufen werden ...
Was ist der beste Weg, um mit dieser Art von Dingen in D umzugehen? Ich könnte jedem Objekt eine "Free" -Mitgliedfunktion hinzufügen, die alle eigenen Ressourcen freigibt und bei beliebigen Objekten "Free" aufruft, aber dies scheint eine fehleranfällige manuelle Operation und ein Rückschritt von C ++ zu sein.
>Gibt es einen besseren Weg, um mit dieser Art von Ding in D umzugehen?
Sie könnten eine Struktur auf dem Stapel verwenden. Das hat eine deterministische Zerstörung. Sie können es sogar mithilfe von std.typecons.RefCounted zurückzählen lassen. Verwenden Sie jedoch keine Struktur im Heap, wenn Sie sicherstellen möchten, dass der Destruktor ausgeführt wird. Im Moment denke ich nicht, dass Destruktoren von Strukturen jemals ausgeführt werden, wenn sie auf den Haufen geworfen werden, weil der GC nicht die Informationen hat, die er dazu benötigt (das sollte irgendwann in der Zukunft).
Wenn Sie jedoch darauf bestehen, den Heap in einer Klasse einzufügen und das Objekt explizit zu zerstören, können Sie clear
darauf aufrufen:
Das wird den Destruktor des Objekts aufrufen und ihn dann in einen ungültigen Zustand setzen, und alles, was danach versucht, es zu benutzen, sollte explodieren (IIRC, die virtuelle Tabelle wird auf Null gesetzt). Aber die Erinnerung ist nicht wirklich freigegeben. Das ist die Aufgabe des GC. Und verwende nicht delete
. Es wird veraltet sein. Ich bin wirklich überrascht, dass es noch nicht ist, da es seit Jahren geplant ist, es loszuwerden.
Und eine Option ist natürlich eine explizite Funktion, die Sie aufrufen, um die Ressourcen freizugeben. Ob das eine gute Idee ist oder nicht, hängt davon ab, was Sie tun. Aber unabhängig davon, Klassen sollen vom GC gesammelt werden und nicht freigegeben werden, wann immer Sie möchten.
Es wird an benutzerdefinierten Zuordnern gearbeitet, die Ihnen mehr Möglichkeiten für die Zuordnung einer Klasse geben würden, und eine davon würde wahrscheinlich eine deterministische Zerstörung von Klassen ermöglichen, aber das ist noch nicht fertig.
Und wenn Sie sich verrückt fühlen, können Sie std.typecons.scoped verwenden, das das bald ersetzt als veraltet gelten Modifizierer scope
(obwohl scope
in anderen Kontexten bleibt - wie scope
-Anweisungen). Es legt eine Klasse auf den Stapel. Aber das ist unsicher (weshalb scope
in diesem Zusammenhang weggeht), und Sie könnten wahrscheinlich auch nur eine Struktur verwenden, wenn Sie das Objekt auf den Stapel kleben.
BEARBEITEN: Sie könnten auch malloc
und free
mit std.conv.emplace , um das Objekt in einen nicht-GC zugewiesenen Speicherbereich zu legen, wie du es in C ++ tun würdest, aber ich denke, dass du den Destruktor explizit aufrufen musst, um ihn auszuführen, da free
nichts über Destruktoren versteht (es ist eine C-Funktion). Das hätte den Vorteil, dass der Speicher zusammen mit der Ressource verschwindet (wohingegen die Verwendung von clear
auf einem Objekt auf dem GC-Heap nur den Inhalt des Objekts zerstören, nicht den Speicher freigeben würde), aber ich weiß nicht, dass das kauft Sie verwenden clear
für ein GC-allokiertes Objekt viel zu oft.
Sie könnten dann jedoch eine freie Funktion ähnlich wie new
erstellen, die die malloc
und emplace
für Sie übernimmt, und dann eine freie Funktion ähnlich wie delete
hat, die den Destruktor und free
aufruft. Das würde Ihnen die gleiche Situation wie C ++ geben. In der Tat, ich frage mich, ob das nützlich genug wäre, um es in die Standardbibliothek zu bekommen. Das ist wahrscheinlich die Art von Sache, die in den benutzerdefinierten Allokatoren landen wird. Es würde mich also nicht überraschen, wenn Sie in naher Zukunft einen benutzerdefinierten Zuordner verwenden könnten, um etwas wie
Und ich würde denken, dass das Ihr Problem ziemlich gut lösen würde, da es im Wesentlichen dasselbe ist wie in C ++, nur mit Bibliotheksfunktionen und nicht mit den integrierten new
und delete
. Ich denke, dass ich es in der Newsgroup ansprechen werde. Ich erwarte, dass es zumindest einige Leute gibt, die solch ein Feature mögen, und das passt gut zu benutzerdefinierten Allokatoren.
Nur zur Klarstellung: Destruktoren werden immer aufgerufen. Wenn ein Objekt zum Zeitpunkt des Beendens der Anwendung noch nicht finalisiert wurde, wird der Finalizer vom GC ausgeführt.
Ich sehe nicht, wie das manuelle Aufrufen einer free () -Funktion zum Löschen des Vertex-Puffers fehleranfälliger ist als die manuelle Verwaltung des Speichers in C ++. Wie auch immer, Sie können sich folgendes anschauen: Ссылка und Ссылка
Tags und Links d direct3d11 direct3d