2

次の関数があるとしましょう (mVertexShaderstd::shared_ptr< ID3D11VertexShader >クラス メンバーであり、mRenderData他の D3D のものを保持する POD です):

void VertexShader::CreateShader( void )
{
    GVertexShader* raw_VertexShader = mVertexShader.get();

    mRenderData->Device->CreateVertexShader(
        mCompiledShader->GetBufferPointer(),
        mCompiledShader->GetBufferSize(),
        NULL,
        &raw_VertexShader
    );

    delete raw_VertexShader;
    raw_VertexShader = NULL;
} 

生のポインターを返すのでmVertexShader.get()、削除するとraw_VertexShaderのポインターに影響しますか、または指しているメモリは同じですが、ポインター自体は完全に異なりますか? mVertexShader.get()

私は後者を推測しているので、そもそもポインターへの参照が存在する理由ですが、正しい考えを持っていることを確認したいと思います。

注:私は現在 MSVC++ を使用していますが、MSVC++ と MinGW/GCC がこれを実装する方法に大きな違いがあるかどうかを聞いていただければ幸いです。

注 2:明確でなかったら申し訳ありません。ここでは D3D のセマンティクスについてはまったく言及していませんが、メモリ管理、データ転送、および動的メモリ割り当てに関する C++ 自体の言語のセマンティクスについては言及していません。その意味で、生のポインターが関数から返されたときに何が起こるかを正確に理解しようとしています。

mVertexShaderつまり、任意の VertexShader への単純な生のポインターを格納していると仮定すると、そのメソッドを呼び出すと、コンテナー内にあるものと同じメモリ アドレスを参照するコピーされたget()ポインターが返されますか、それともまったく新しいものですか?メモリが別のアドレスを指している状態で、コピーされて返されたポインタ全体ですか?shared_ptr

4

2 に答える 2

6

これは、実際には完全に のセマンティクスに関するものstd::shared_ptrです。この言語は、オブジェクトへのポインターを返す方法、オブジェクトのコピーを作成してそのポインターを返す方法、またはオブジェクトの参照カウントを増やしてそれへのポインターを返す方法を完全にサポートしています。必要に応じて、これらすべてを行うことができます。

共有ポインターのgetメソッドは、オブジェクトへの生のポインターを返すだけです。コピーは行いません。次の 2 つの理由から、このポインターを使用しない でください。delete

  1. 別のオブジェクトが同じオブジェクトへの共有ポインターを持っている可能性があり、その下からオブジェクトを削除することになります。(これが共有ポインタのポイントです。)

  2. 最後の共有ポインタがなくなると、オブジェクトは削除されます。オブジェクトを 2 回削除することは UB であり、コードがクラッシュする可能性があります。(これは、共有ポインタのポイントでもあります。)

共有ポインタに仕事をさせてください。

共有ポインターを呼び出す場合はget、取得した生のポインターを使用できる限り、その共有ポインターを保持する必要があることに注意してください。そうしないと、オブジェクトが存在しなくなる可能性があります。共有ポインターのロジックは、オブジェクトを参照する共有ポインターを少なくとも 1 つ保持している限り削除されず、そのような最後の共有ポインターがなくなると、オブジェクトは自動的に削除されるというものです。

于 2012-07-29T07:40:30.917 に答える