8

C ++でDirect3Dを使用する場合、たとえば「ID3D11Buffer *vertexBuffer_」を含む「Cube」クラスを記述し、そのCubeオブジェクトのデストラクタがvertexBuffer _-> Release()を呼び出すようにすることができます。

「unique_ptrcube_」オブジェクトを含む「Scene」クラスを持つことができます。シーンを削除すると、キューブが削除され、その結果、使用しているD3Dリソースのリリースが呼び出されることがわかります。

DIではこれを行うことはできません。デストラクタを書くことはできますが、いつ呼び出されるかわかりません。GCがメモリを必要としない場合、それらが呼び出されることはありません...

では、Dでこの種のことを処理するための最良の方法は何ですか?各オブジェクトに「Free」メンバー関数を追加して、それ自体のリソースをすべて解放し、所有するオブジェクトに対して「Free」を呼び出すこともできますが、これはエラーが発生しやすい手動操作であり、C++から一歩後退しているようです。

Dでこの種のものを処理するためのより良い方法はありますか?

4

2 に答える 2

6

スタックで構造体を使用できます。それは決定論的な破壊を持っています。std.typecons.RefCountedを使用して、再カウントすることもできます。ただし、デストラクタが実行されることを保証したい場合は、ヒープ上で構造体を使用しないでください。現時点では、構造体のデストラクタがヒープに配置された場合に実行されることはないと思います。これは、GCに必要な情報がないためです(これは、将来も)。

ただし、クラスのヒープに配置することを主張し、オブジェクトを明示的に破棄したい場合は、次のように呼び出すことができますclear

clear(obj);

これにより、オブジェクトのデストラクタが呼び出され、無効な状態になります。その後、オブジェクトを使用しようとすると、すべてが爆発します(IIRC、仮想テーブルはゼロになります)。しかし、メモリは実際には解放されません。それがGCの仕事です。そして、使用しないでくださいdelete。非推奨になります。何年にもわたってそれを取り除くことが計画されていたので、私は実際にそれがまだ行われていないことに驚いています。

そしてもちろん、1つのオプションは、リソースを解放するために呼び出す明示的な関数を持つことです。それが良い考えであるかどうかは、あなたが何をしているかに依存します。ただし、クラスはGCによって収集されることを目的としており、必要に応じて解放されることはありません。

カスタムアロケータで作業が行われています。これにより、クラスを割り当てる方法についてより多くのオプションが提供され、そのうちの1つで、クラスをより決定論的に破棄できるようになりますが、まだ準備ができていません。

また、気が狂っている場合は、std.typecons.scopedを使用できます。これは、間もなく非推奨になる型修飾子を置き換えますscope(ただし、ステートメントscopeなどの他のコンテキストでは使用されません)。scopeクラスをスタックに置きます。しかし、それは安全ではありません(これがscope、このコンテキストでなくなる理由です)。オブジェクトをスタックに貼り付ける場合は、おそらく構造体を使用する方がよいでしょう。

編集:また、std.conv.emplaceを使用mallocして、C ++の場合と同様に、GCで割り当てられていないメモリのチャンクにオブジェクトを配置することもできますが、それを取得するには、デストラクタを明示的に呼び出す必要があると思います。デストラクタ(C関数)について理解していないため、実行します。これには、リソースとともにメモリがなくなるという利点があります(一方、GCヒープ上のオブジェクトで使用すると、メモリが解放されるのではなく、オブジェクトのコンテンツが破棄されるだけです)。GCに割り当てられたオブジェクトで使用します。freefreeclearclear

ただし、とを実行するのと同様の無料関数を作成してからnew、デストラクタとを呼び出すのと同様の無料関数を作成すると、C++と同じ状況になります。実際、それが標準ライブラリにするのに十分役立つのではないかと思います。それはおそらく、カスタムアロケータで終わるようなものです。したがって、比較的近い将来、カスタムアロケータを使用して次のようなことを実行できたとしても、まったく驚かないでしょう。mallocemplacedeletefree

auto obj = customAllocObj.create!MyObj(args);
//Do stuff...
customAllocObj.destroy(obj);

newそして、それがC ++での問題と本質的に同じであり、組み込みのandではなくライブラリ関数を使用することを考えると、問題はかなりうまく解決すると思いますdelete。ニュースグループで取り上げると思います。そのような機能を望んでいる人が少なくとも何人かいると思いますが、それはカスタムアロケータにうまく適合しているようです。

于 2012-02-23T11:18:16.300 に答える
2

明確にするために:デストラクタは常に呼び出されます。アプリケーションがシャットダウンするまでにオブジェクトがファイナライズされていない場合、GCはファイナライザーを実行します。

頂点バッファを削除するためにfree()関数を手動で呼び出すことが、C++でメモリを手動で管理する必要があるよりもエラーが発生しやすい方法がわかりません。とにかく、あなたは見たいかもしれません:http ://www.dlang.org/phobos/std_typecons.html#scopedとhttp://www.dlang.org/phobos/std_typecons.html#RefCounted

于 2012-02-23T10:09:48.293 に答える