1
#include <iostream>
#include <boost/shared_ptr.hpp>

class implementation
{
public:
    ~implementation() { std::cout <<"destroying implementation\n"; }
    void do_something() { std::cout << "did something\n"; }
};

void test()
{
    boost::shared_ptr<implementation> sp1(new implementation());
    std::cout<<"The Sample now has "<<sp1.use_count()<<" references\n";

    boost::shared_ptr<implementation> sp2 = sp1;
    std::cout<<"The Sample now has "<<sp2.use_count()<<" references\n";

    sp1.reset();
    std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" references\n";

    sp2.reset();
    std::cout<<"After Reset sp2.\n";
}

int main()
{
    test();
}

実行結果は以下です。

$ ./a.out 
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 1 references
destroying implementation
After Reset sp2.

上記のコードを確認してください。私にとって最初に不明なことは、以下の文が何を意味するかということです。sp1 はポインタですか?機能?または関数へのポインタ?とnew implementation()はどういう意味ですか? sp1()?の引数は?

boost::shared_ptr<implementation> sp1(new implementation());

2 番目の質問は、とdestroying implementationの結果として与えられるです。しかし、がコメントアウトされている場合、結果は次のようになります。sp1.reset()sp2.reset()sp1.reset()

$ ./a.out 
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 2 references
After Reset sp2.
destroying implementation

のみをコメントアウトするsp2.reset()と、結果は次のようになります。

$ ./a.out 
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 1 references
After Reset sp2.
destroying implementation

sp1.reset()つまり、両方を呼び出しsp2.reset()て shared_ptr を解放する必要はありません。

4

2 に答える 2

2

私にとって最初に不明なことは、以下の文が何を意味するかということです。sp1 はポインタですか?機能?または関数へのポインタ?

spですshared_ptr<implementation>。それが何を意味するのかわからない場合は、参照ドキュメントとチュートリアルがあります。しかし、短いバージョンは次のとおりです。これは、implementation *ポインターと同様に機能するオブジェクトですが、使い終わったときにオブジェクトを自動的に削除するimplementation点が異なります。それが「スマートポインター」です。Ashared_ptrは特定の種類のスマート ポインターであり、必要な数のコピーを作成でき、それらのコピーがすべてなくなったときに基になるオブジェクトのみを削除します。

このように見える 1 つの方法は、ガベージ コレクターを必要としない単純な形式のガベージ コレクションを提供することです。

もう 1 つの見方は、C++ の中心的なイディオムの 1 つであるResource Acquisition Is Initialization (RAII) の一部です。

new implementation() はどういう意味ですか? sp1()?の引数は?

new implementation()新しいimplementationオブジェクトを作成し、その既定のコンストラクターを呼び出し、implementation *ポインターを返します。そのポインターは、shared_ptrコンストラクターへの引数です。これは、がその新しいオブジェクトsp1へのスマート ポインターになることを意味します。そのため、オブジェクトは破棄されて削除され、後でそのオブジェクトから作成されたコピーはすべてなくなります。implementationsp1

2 番目の質問は、sp1.reset() と sp2.reset() の結果として実装の破棄が行われるということです。

実はそれは、新しい価値観を指摘されたり、破壊されsp1たりした結果として与えられたものです。は前者を実行しますが、何もせずに範囲外にするだけで後者が実行されます。それが RAII の重要な部分です。sp2reset

つまり、sp1.reset() と sp2.reset() の両方を呼び出して shared_ptr を解放する必要はありません。

丁度。を明示的に呼び出したいと思うことはめったにありませんreset。RAII の要点は、これらを手動で管理する必要がないことです。オブジェクト( などshared_ptr)を初期化してリソースへのアクセスを取得し、そのオブジェクトを手放してアクセスを解放します。

役に立つケースがいくつかあります。たとえばshared_ptr、オブジェクトのメンバーとして があり、そのオブジェクトが所有するリソースよりもはるかに長く存続する場合は、 を呼び出して早期に解放できますreset。(その間にコピーを他の人に渡したとしても、それが早期に削除されることを心配する必要はありません。それは、それを存続させることにもはや関与していないことを意味します。)

于 2013-01-01T07:50:54.267 に答える
1

コメントで指摘されたように、SO 形式から学ぶべき基本事項がいくつかあります。

ただし、最後の質問には回答が必要です。

つまり、sp1.reset() と sp2.reset() の両方を呼び出して shared_ptr を解放する必要はありません。

ポインターの 1 つだけをリセットした場合に実装が破棄される理由は、スコープの終了、つまりから戻るためです。これによりtest()shared_ptrs がスコープ外に出て破棄され、その結果、管理対象オブジェクトが破棄されます。

于 2013-01-01T07:55:46.903 に答える