2012-02-23 13 views
8

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

私は "unique_ptr cube_"オブジェクトを含む "Scene"クラスを持つことができます。シーンを削除すると、キューブが削除され、その結果、使用しているD3Dリソースが解放されることがわかります。

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

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

Dでこのようなことを処理するより良い方法はありますか?

答えて

6

あなたはスタック上で構造体を使うことができます。 そのには確定的な破壊があります。あなたはstd.typecons.RefCountedを使ってそれを参照することさえできます。ただし、デストラクタが実行されることを保証したい場合は、ヒープ上で構造体を使用しないでください。現時点では、構造体のデストラクタはヒープ上に置かれても実行されないと考えています。なぜなら、GCには必要な情報がないからです(これは、将来も)。

しかし、あなたはクラスでヒープ上にそれを置くことを主張し、あなたが明示的にオブジェクトを破棄したい場合は、その後、あなたはそれにclearを呼び出すことができます。

clear(obj); 

オブジェクトのデストラクタを呼び出しますし、それを無効な状態にして、それを使いこなそうとするものは爆発するはずです(IIRC、仮想テーブルはゼロになります)。しかし、記憶は実際に解放されません。それがGCの仕事です。 deleteは使用しないでください。それは廃止される予定です。私はそれがまだそれを取り除く年齢のために計画されているので、それはまだされていないことは実際に驚いている。

もちろん、リソースを解放するために呼び出す明示的な関数を用意することもできます。それが良いアイデアかどうかは、あなたがやっていることによって決まります。ただし、クラスに関係なく、GCによって収集されることを意図しており、いつでもクラスを解放することはできません。

カスタムアロケータの作業が行われています。これにより、クラスの割り当て方法のオプションが増えます。そのうちの1つは、おそらくクラスのより確定的な削除を可能にしますが、まだ準備ができていません。

そして、あなたは狂った感じているならば、あなたは(scopeその他のコンテキストで周りに付着しているが - などscopeなどのステートメント)すぐに廃止されるための型修飾子scopeを置き換えるstd.typecons.scopedを、使用することができます。それはクラスをスタックに置きます。しかし、それは安全ではありません(なぜなら、scopeはこのコンテキストではなくなります)。スタックにオブジェクトを貼り付ける場合は、おそらく構造体を使用するだけです。

EDIT:また、あなたはC++であるだろうように、メモリの非GC割り当てられたチャンクにオブジェクトを配置するstd.conv.emplacemallocfreeを使用することができますが、私はあなたが明示的に呼び出す必要があるだろうと思いますfreeはデストラクタ(これはC関数)については理解していないので、デストラクタを実行するにはこれは、リソースと共にメモリがなくなるというメリットがあります(GCヒープ上のオブジェクトにclearを使用すると、オブジェクトの内容が破棄され、メモリが解放されません)が、 GC割り当てオブジェクト上でclearを使用します。

しかし、あなたはあなたのためにmallocemplaceを行いnewに似たフリー機能を作成することができ、その後、あなたはCと同じような状況を与えるだろうデストラクタとfreeを呼び出しdeleteに似たフリー機能を、持ってい++ 。実際には、それが標準ライブラリに入るのに十分に役立つのだろうかと思います。それはおそらく、カスタムアロケータで終わることでしょう。だから、比較的近い将来に、あなたは

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

ような何かをするためにカスタムアロケータを使用することができれば、それがすべてで、私は驚かないだろうと私はそれがかなりよくそれは本質的だと与えられたあなたの問題を解決するだろうと思うだろう組み込みのnewdeleteではなく、ライブラリ関数を使っているだけで、C++で同じことができます。私はニュースグループにそれを掲示すると思います。私はこのような機能がほしいと思う人々が少なくともいると思います。それはカスタムアロケータにうまく収まるようです。

+0

包括的な答えをありがとう! オブジェクトの寿命がそれより長いため、スタック上で構造体を使用できるかどうかはわかりません。クリアは私のために働くかもしれませんが、それは私自身のclear()関数と違っているようには見えません。私はとにかく考えてもっと多くのことを私に与えました:) – jcoder

+0

@ JohnB私はあなたがおそらく構造体を渡していると仮定していましたが、あなたの状況によっては動作しない可能性があります。あなた自身の関数を実行しているなら、その中にデストラクタを呼び出さないようにアドバイスします - それは単に問題を尋ねるだけです(デストラクタはあなたの関数がリソースを解放するものであれコールすることができます)。したがって、実際にデストラクタを呼びたい場合は、 'clear'を使います。あなたがしたいのはリソースを解放するだけであれば、そのオブジェクトを破壊するのではなく、別の関数を特別に呼び出す方が意味があるかもしれません。それはあなたのコードに依存します。 –

2

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

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

+2

問題は、メモリが解放されたときにデストラクタが呼び出されることです。これは、GCがオブジェクトがそれ以上参照されないことをGCが認識したときに、将来、ある時点になります。私は、D3Dオブジェクトを将来的には未定義のポイントではなく、すぐにリリースする必要があります。 – jcoder

+0

['delete'](http://www.d-programming-language.org/expression.html#DeleteExpression)? "UnaryExpressionがクラスオブジェクト参照で、そのクラスのデストラクタがある場合、デストラクタはそのオブジェクトインスタンスに対して呼び出されます。" –

+0

'delete'が言語から削除されています。それを使用しないでください。オブジェクトのデストラクタを呼び出してオブジェクトを無効にする 'clear'を使うことはできますが、メモリを解放することはありません。それがGCの仕事です。決定論的破壊が必要な場合は、構造体を使用します。 –

関連する問題