1

これがシナリオです。Program という名前のクラスがあり、頂点、ジオメトリ、フラグメント シェーダーの 3 つの shared_ptr を保持しています。Shader オブジェクトが構築されると、glCreateShader でシェーダーが作成され、コンパイルも行われます。

Shader デンストラクタは自動的に glDeleteShader を呼び出します。したがって、問題は、次のことを行う場合です。

  1. シェーダー オブジェクトを作成します。
  2. コピーします。
  3. コピーを破棄します。

また、コピーが破棄されると glDeleteShader が呼び出されるため、元のコピーも無効になります。それは設計上の問題だと思います。

そのため、ポインターを使用するだけでこの問題を回避しました。これで、Program クラスがシェーダーを保持します。頂点、ジオメトリ、およびフラグメント シェーダー オブジェクトに shared_ptr を返すメソッドを作成しました。私の疑問は、次のように shared_ptr を返す必要があるかどうかです。

const shared_ptr<Shader>& getVertex_shader_ptr() const
{
    return vertex_shader_ptr;
}

またはこのように:

shared_ptr<Shader> getVertex_shader_ptr() const
{
    return vertex_shader_ptr;
}

私が恐れているのは、上で説明した問題が再び発生することです。shared_ptr の割り当てが解除され、OpenGL シェーダーが無効になります。

4

4 に答える 4

5

シェーダーがNULLであることが有効でない限り、シェーダーへの参照を返す必要があります。

const Shader& getVertex_shader() const
{
    return vertex_shader;
}

シェーダーがNULLであることが有効であるが、それを削除するのはプログラムのみである場合は、ポインターを返すだけです。

const Shader* getVertex_shader_ptr() const ...

共有ポインターのセマンティクスは、シェーダーの明確な所有権がない場合に使用されます。その場合は、値で返します。セマンティクスは、プログラムの2つの部分が、クリーンアップされていないオブジェクトに関心を持っており、どちらもオブジェクトを存続させる方法を必要としているということです。

shared_ptr<Shader> getVertex_shader_ptr() const ...
于 2013-01-30T15:42:20.417 に答える
2

値で返す方がいいです。参照によって戻る場合、ある時点でインスタンスが破棄され、一部の変数がまだshared_ptrへの参照を保持していると、shared_ptrへの参照がぶら下がっている可能性があります。

この状況は、スマートポインターが回避するはずだった状況とまったく同じですが、参照カウントは、コピーによって返されることを回避した場合にのみ安全に機能します。これにより、ここでshared_ptrを使用するポイント全体が無効になります。

于 2013-01-30T15:38:09.530 に答える
2

ここはどちらでもいいです。

これはメンバーなので、呼び出し元が参照によってそれを保持していない限り、参照を返しても安全Programです。

非 const 参照によって返された場合、呼び出し元は、ポインターの他のコピーが存在しない場合resetに呼び出すポインターを呼び出すことができます。glDeleteShaderただし、それはあなたが望むように動作します -Shaderそれへの参照が存在しなくなった場合にのみ破棄されます。

個人的には値で返しshared_ptrますが、それは個人的な好みです。

Program編集: a (ない a )をコピーするときの正確性について心配しているという意味であると仮定するとShader、それについても心配する必要はありません。2 つの s には、両方の s が破壊されるまで破壊されないProgram同じへの shared_ptrs があります。これはあなたが望むものかもしれませんし、そうでないかもしれません (完全に別のコピーを割り当てたいかもしれません) が、安全です。ShaderProgramShader

于 2013-01-30T15:33:03.200 に答える
1

根底にある共有ポインターの問題についてあまり知らなかったので、Thiago Macieira (おそらく Qt/Trolltech の従業員) によるこの投稿は、値を返すか、または を返すかについてより良いアイデアを得るのにかなり役立ちましたconst&: http://lists.trolltech.com /qt-interest/2007-11/thread00209-0.html

constその投稿から引用すると、関数から値を返すためのコア引数は次のとおりです。

その理由は次のとおりです。

T at(const Key& k) const;

それ以外の:

const T &at(const Key &k) const;

Qtのどこでもそうだからです。refs-to-const はどこにも返しません。ref-to-const を返すには、変数がどこかに存在する必要があり、クラスの内部構造が必要になります。値を返すことで、内部でやりたいことが何でもできます。

それがあなたの問題に当てはまるかどうかはわかりません...(まだ自分自身を学んでいます;))

于 2013-01-30T15:59:20.680 に答える