2016-06-28 14 views
0

私はこのようなものがあります:パラメータを渡すときに作成されるオブジェクトは削除する必要がありますか?

class GLSLShader { 
    public: 
     GLSLShader(GLenum); 
     ~GLSLShader(); 
}; 

class GLSLProgram { 
    public: 
     GLSLProgram(GLSLShader *, GLSLShader *); 
     ~GLSLProgram(); 

    private: 
     GLSLShader *m_VertexShader; 
     GLSLShader *m_FragmentShader; 
}; 

GLSLProgramコンストラクタは次のように呼ばれるように起こっている:

GLSLProgram program(new GLSLShader(GL_VERTEX_SHADER), new GLSLShader(GL_FRAGMENT_SHADER)); 

私の質問はどこで割り当てられたシェーダオブジェクトを削除する必要があります。私はGLSLProgramのデストラクタでそれを削除する必要がありますか?それとも、以下のコードのように別の方法で管理する必要がありますか?

GLSLShader *vertex = new GLSLShader(GL_VERTEX_SHADER); 
GLSLShader *fragment = new GLSLShader(GL_FRAGMENT_SHADER); 
GLSLProgram program(vertex, fragment); 
delete vertex; 
delete fragment; 
+2

[使用RAII](http://stackoverflow.com/questions/395123/raii-and-smart-pointers-in-c)Rakete1111 @ – Rakete1111

+1

:彼はRAIIを使用しています。 'GLSLShader'のデストラクタは、コンストラクタが割り当てるリソースをクリーンアップします。彼はちょうどRAII *を本当にひどく使っています* –

+2

**所有権**の質問です。 GLSLProgramがこのオブジェクトの所有者であると仮定すると、GLSLProgramは破壊時にそれらを削除する必要があります。 GLSLProgramがそれらと一緒に動作すると仮定すると、それは許されません。 – ilotXXI

答えて

2

次の2つの基本的な問題を抱えています。

最初の問題は、RAIIオブジェクトを誤って使用していることです。 RAIIオブジェクトのポイントは、newdeleteを明示的に使用するのではなく、自動変数を使用してオブジェクトのライフタイムを管理することです。 GLSLShadernewを使用することで、そのポインタをRAIIコンテナにラップせずに、デストラクタが行う作業を効果的に軽減できます。

GLSLProgramコンストラクタはポインタでオブジェクトを取得しないでください。それはconst&によってそれらを取る必要があります。これにより、呼び出し元がオブジェクトの存続期間を簡単に決めることができます。

第2の問題は論理的です。 GLSLProgramが与えられたシェーダオブジェクトの破壊に責任を負う理由はありません。 GLSLシェーダオブジェクトはが再利用されるので、呼び出しコードまででなければなりません。

したがって、GLSLProgramは、これらのオブジェクトを破壊しようとしないでください。しかし、プログラムを正常に作成した後、コンストラクターは、でGLSLプログラムからGLSLシェーダーを切り離す必要があります。また

GLSLShader vertex(GL_VERTEX_SHADER); 
GLSLShader fragment(GL_FRAGMENT_SHADER); 
//Fill `vertex` and `fragment` with actual shader code. 
GLSLProgram program(vertex, fragment); 
//Destructors for `vertex` and `fragment` will take care of themselves. 

が、あなたはいくつか他のものに注意する必要があります:

全体的に、あなたのコードは次のようになりべき

  1. プログラムが2つの以上のシェーダオブジェクトを作成することができます 。だから、あなたはそのような多くのオブジェクトを取ることができる代替のコンストラクタを持つべきです。

  2. Separable programsシェーダオブジェクトをまったく使用せずに、文字列から直接作成することができます。

+0

RAIIの存在を認識していなかったので、誤ってRAIIを使用していたはずです。あなたが言ったように、再利用できるので、 'GLSLProgram'がシェーダーの破壊に責任を持つべきかどうかは疑いがありませんでした。しかし、別の質問である 'GLSLProgram'は' const& 'によってそれらを取るべきですが、メンバ変数はポインタのままにしておきますか? –

+0

他のことについては、私はその両方の状況を認識しています。私はちょうどまだそれを実装するのには至りませんでした。 –

+1

@JeanCatanho: "*メンバ変数はポインタを保持する必要があります*"シェーダのメンバ変数はありません。プログラムオブジェクトはそれらを*保持してはいけません。作成したプログラムをリンクし、プログラムを正常に作成した後にシェーダを切り離し、終了する必要があります。コンストラクタがその仕事をした後、コンストラクタはもはや必要ありません。 –

1

私はGLSLProgramのデストラクタでそれを削除する必要がありますか、私はそれが依存違っ

、それを管理する必要があります。

GLSLProgram以外のものは、これらの動的オブジェクトにアクセスする必要がありますか?そのようなオブジェクトは、それを指すGLSLProgramインスタンスよりも寿命が長いことがありますか?両方にyesと答えると、メモリはprogramによってのみ管理することはできません。

どちらの場合でも、ダイナミックオブジェクトの破壊のみを担当するRAIIオブジェクトにメモリ管理を委任すると、正しいプログラムを作成する方がはるかに簡単です。

一方、GLSLProgramがメモリを単独で管理できる場合は、確実にメモリを割り当てる必要があります。さらに、ダイナミックアロケーションを使用する理由はまったくないようです。特定の理由がない限りメンバーオブジェクトを代わりに使用することをお勧めします。問題の試みを考える

、私は次のことをお勧め:

class GLSLProgram { 
    public: 
     GLSLProgram(): 
      m_VertexShader(GL_VERTEX_SHADER), 
      m_FragmentShader(GL_FRAGMENT_SHADER) {} 

    private: 
     GLSLShader m_VertexShader; 
     GLSLShader m_FragmentShader; 
}; 
+0

私はRAIIを認識していなかったので、これをどう対処するか正確には分かりませんでしたが、GLSLProgramがメモリを単独で管理できない場合でも、ダイナミックアロケーションを使用する理由はありません。 –

関連する問題