次の一連のポインターの違いは何ですか?本番コードで各ポインターを使用するのはいつですか?
例に感謝します!
scoped_ptr
shared_ptr
weak_ptr
intrusive_ptr
製品コードでブーストを使用しますか?
各スマートポインターを割り当てることができるプロパティがある場合は簡単です。 3つの重要なプロパティがあります。
1つ目は、スマートポインターがオブジェクトを所有していないため、オブジェクトを削除できないことを意味します。 2番目は、1つのスマートポインターのみが同じオブジェクトを同時に指すことができることを意味します。スマートポインターが関数から返される場合、たとえば、所有権は返されたスマートポインターに転送されます。
3番目は、複数のスマートポインターが同じオブジェクトを同時に指すことができることを意味します。これはrawポインターにも適用されますが、rawポインターには重要な機能がありません。owningであるかどうかを定義しません。すべての所有者がオブジェクトを放棄した場合、所有権の共有スマートポインターはオブジェクトを削除します。この動作は頻繁に必要になるため、共有所有のスマートポインターが広く普及しています。
一部の所有スマートポインターは、2番目も3番目もサポートしません。したがって、関数から返されたり、他の場所に渡されることはありません。これは、スマートポインターがローカルに保持され、オブジェクトがスコープ外に出た後にオブジェクトを解放するように作成されるというRAII
の目的に最も適しています。
所有権の共有は、コピーコンストラクターを使用して実装できます。これにより、自然にスマートポインターがコピーされ、コピーとオリジナルの両方が同じオブジェクトを参照します。所有権の移転は、現在C++で実際に実装することはできません。1つのオブジェクトから言語でサポートされる別のオブジェクトに何かを移転する手段がないためです。関数からオブジェクトを返そうとすると、オブジェクトがコピーされます。したがって、所有権の移転を実装するスマートポインターは、コピーコンストラクターを使用して所有権の移転を実装する必要があります。ただし、コンテナの要素のコピーコンストラクターの特定の動作は、これらのスマートポインターのいわゆる「移動コンストラクター」動作と互換性がないため、コンテナーでの使用が中断されます。
C++ 1xは、いわゆる「コンストラクターの移動」と「代入演算子の移動」を導入することで、所有権の譲渡をネイティブにサポートします。また、unique_ptr
と呼ばれる所有権の譲渡スマートポインターも付属しています。
scoped_ptr
は、転送も共有もできないスマートポインターです。ローカルでメモリを割り当てる必要がある場合に使用できますが、スコープ外になった場合は必ず解放してください。ただし、必要に応じて、別のscoped_ptrと交換できます。
shared_ptr
は、所有権を共有するスマートポインターです(上記の3番目の種類)。参照カウントであるため、その最後のコピーがスコープ外になり、管理対象オブジェクトを解放するタイミングを確認できます。
weak_ptr
は非所有のスマートポインターです。参照カウントを追加せずに(shared_ptrによって管理される)管理対象オブジェクトを参照するために使用されます。通常、shared_ptrから生のポインタを取得し、それをコピーする必要があります。しかし、オブジェクトが実際に削除されたことを確認する方法がないため、これは安全ではありません。したがって、weak_ptrは、shared_ptrによって管理されるオブジェクトを参照することで手段を提供します。オブジェクトにアクセスする必要がある場合、オブジェクトの管理をロックして(別のスレッドでshared_ptrがオブジェクトの使用中に解放することを避けるため)、それを使用できます。 weak_ptrがすでに削除されたオブジェクトを指している場合、例外をスローして通知します。 weak_ptrの使用は、循環参照がある場合に最も有益です。参照カウントは、このような状況に簡単に対処できません。
intrusive_ptr
はshared_ptrに似ていますが、参照カウントをshared_ptrに保持せず、管理対象のオブジェクトで定義する必要のあるヘルパー関数のカウントをインクリメント/デクリメントします。これには、すでに参照されているオブジェクト(外部参照カウントメカニズムによって参照カウントがインクリメントされる)をintrusive_ptrに詰め込むことができるという利点があります。参照カウントはスマートポインターの内部ではなく、スマートポインターが既存の参照カウント機構。
unique_ptr
は、所有権の譲渡ポインターです。コピーすることはできませんが、C++ 1xの移動コンストラクターを使用して移動できます。
unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
これはstd :: auto_ptrが従うセマンティックですが、移動に対するネイティブサポートが欠落しているため、落とし穴なしで提供することはできません。 unique_ptrは、移動セマンティクスの主要な機能の1つである一時的な他のunique_ptrからリソースを自動的に盗みます。 auto_ptrは、unique_ptrを支持して、次のC++標準リリースで非推奨になります。 C++ 1xでは、コンテナにコピーすることはできず、移動のみが可能なオブジェクトを詰めることもできます。したがって、unique_ptrをベクトルに詰め込むことができます。これについてもっと詳しく知りたい場合は、ここで立ち止まって、 すばらしい記事 を参照してください。
scoped_ptrが最も簡単です。範囲外になると破棄されます。次のコードは違法です(scoped_ptrsはコピー不可)が、ポイントを説明します:
std::vector< scoped_ptr<T> > tPtrVec;
{
scoped_ptr<T> tPtr(new T());
tPtrVec.Push_back(tPtr);
// raw T* is freed
}
tPtrVec[0]->DoSomething(); // accessing freed memory
shared_ptrは参照カウントです。コピーまたは割り当てが発生するたびに、参照カウントがインクリメントされます。インスタンスのデストラクタが起動されるたびに、生のT *の参照カウントが減ります。 0になると、ポインターは解放されます。
std::vector< shared_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
// This copy to tPtrVec.Push_back and ultimately to the vector storage
// causes the reference count to go from 1->2
tPtrVec.Push_back(tPtr);
// num references to T goes from 2->1 on the destruction of tPtr
}
tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe
weak_ptrは、共有ポインタへの弱参照であり、ポイント先のshared_ptrがまだ存在するかどうかを確認する必要があります
std::vector< weak_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
tPtrVec.Push_back(tPtr);
// num references to T goes from 1->0
}
shared_ptr<T> tPtrAccessed = tPtrVec[0].lock();
if (tPtrAccessed[0].get() == 0)
{
cout << "Raw T* was freed, can't access it"
}
else
{
tPtrVec[0]->DoSomething(); // raw
}
intrusive_ptrは通常、使用する必要があるサードパーティのスマートptrがある場合に使用されます。無料の関数を呼び出して、参照カウントを追加および減分します。詳細については、ドキュメントを後押しするには link を参照してください。
ブーストスマートポインターの調査では、 boost::ptr_container
を見落とさないでください。それらは、例えばstd::vector<boost::shared_ptr<T> >
が遅すぎる場合に非常に貴重です。
次に、ドキュメントを参照することについてのアドバイスをします。見た目ほど怖くない。そして、いくつかの短いヒント:
scoped_ptr
-範囲外になると自動的に削除されるポインター。注-割り当てはできませんが、オーバーヘッドは発生しませんintrusive_ptr
-smart_ptr
のオーバーヘッドのない参照カウントポインター。ただし、オブジェクト自体には参照カウントが格納されますweak_ptr
-shared_ptr
と連携して、循環依存関係を引き起こす状況に対処します(ドキュメントを読み、GoogleでNice pictureを検索してください;)shared_ptr
boostが提供するものから)スマートポインターの最も一般的で最も強力な(そして重い)auto_ptr
もあります。これは、コントロールがスコープを離れると、それが指すオブジェクトが自動的に破棄されることを保証します。ただし、コピーセマンティクスは他の人とは異なります。unique_ptr
----(C++ 0xに付属編集する応答:はい