12

TR1 では、shared_ptr、weak_ptr、scoped_ptr、unique_ptr などが導入されました。

これらの型の間のさまざまな変換/型昇格規則を知りたいです。

たとえば、scoped_ptr が shared_ptr に割り当てられるとどうなりますか? そのような変換は可能ですか/意味がありますか?また、そのような変換のユースケースは何ですか?

(仕様に表はありますか?)

4

3 に答える 3

13

まず、質問に対するいくつかの修正:

  • scoped_ptrBoost の一部であり、C++ TR1 にも C++0x にも含まれていません (C++0x では、従来使用されていたunique_ptr場所で使用できると予想さscoped_ptrれます)。

  • unique_ptrC++ TR1 の一部ではありません。これは C++0x の一部です (C++0x でのみ利用可能な右辺値参照と移動セマンティクスに依存しているため)。

あなたの質問に答えるに はshared_ptrweak_ptr手を取り合ってください。が所有するオブジェクトは、 からshared_ptrも参照できますweak_ptr。それらは補完的です。

Aunique_ptrは、それが管理するオブジェクトの唯一の所有権を持っています。他の誰もオブジェクトの所有権を持つことはできません。これは、 の所有権セマンティクスの反対shared_ptrですunique_ptr。あなたが共有しshared_ptrている、一意ではない所有権と。

shared_ptraから aを構築できunique_ptrます。これを行うと、unique_ptrはオブジェクトの所有権を失います。これは、特定unique_ptrのオブジェクトが常にオブジェクトの唯一の所有者であることを常に知っているため、その所有権を解放できるため機能します。

オブジェクトが によって所有されると、特定の がオブジェクトの唯一の所有者であるshared_ptrという保証がないため、オブジェクトの所有権を解放することはできません。shared_ptr

于 2010-11-21T08:52:05.397 に答える
3

2 つのクラスAand B(スマート ポインター型である可能性があります) が与えられた場合、 type のインスタンスを type に変換する主な方法は 4 つありBますA

  • Aのアクセス可能な基本クラス オブジェクトB(たとえば、Bから公に派生したものA) であり、変換によって、参照またはポインターの型をスライスしたり、単純に調整したりできます。(意図的な取り消し線)。

  • Aを受け取るアクセス可能なコンストラクターがありますB

  • Bを生成するアクセス可能な変換演算子がありますA

  • Bを受け取ってを生成する関数がいくつかありA、その関数を呼び出しています。

スマート ポインターの場合、継承は正しくない変換を許容するため、変換を容易にするために使用されません。したがって、上の取り消し線。たとえば、SmartPtr<Derived>から公に継承された場合SmartPtr<Base>、 を行うことができSmartPtr<Base>& spBase = spDerived;、たとえば、これはかなり問題になります... 適切に高い抽象化レベルでは、これはポインタ変換spBase = spOtherDerivedの場合と本質的に同じ問題です。constFAQ 項目18.17 「Foo** → Foo const** の変換中にエラーが発生するのはなぜですか?」を参照してください。.

そのため、スマート ポインターの変換は通常、最後の 3 つの箇条書き、つまりコンストラクター、変換演算子、および名前付き変換関数によって表現されます。

基本的に、C++0x には非推奨の を無視して 3 つのスマート ポインターがありますauto_ptr

  • std::unique_ptr単一オブジェクト用。

  • std::unique_ptr配列用。

  • std::shared_ptr単一オブジェクト用。

unique_ptr昔のように名義変更を表現auto_ptrします。しかし、auto_ptr配列をサポートしていませんでした。unique_ptrあり、それは可能な変換に影響します。

単一オブジェクトの場合、unique_ptrコンストラクターを介して、対応する生ポインターが行う変換をサポートします。unique_ptr他のタイプのを受け取るテンプレート化されたコンストラクターがあります。たとえば、C++0x ドラフト N3126 §20.9.10.2 を参照してください。

しかし、生のポインターと同じくらい危険な配列の場合! そのため、配列の場合、ベース/派生変換は提供されunique_ptrません。たとえば、C++0x ドラフト N3126 §20.9.10.3 を参照してください。

は共有所有権を表現しunique_ptrながら所有権の移転を表現するため、 からへの一般的な安全な変換はあり得ません。ただし、逆に、Boostには を取得するコンストラクターがあり、C++0xはこれを保持し (これも保持)、自然に を取得するコンストラクターを追加します。C++0x ドラフト N3126 §20.9.11.2/1 を参照してください。shared_ptrshared_ptrunique_ptrshared_ptrauto_ptrshared_ptrunique_ptr

shared_ptrコンストラクターおよび概念的に「キャスト」を実装するフリー関数を介して、基本/派生変換を提供します。基本的にこれはshared_ptr、クラス型オブジェクトの配列に直接使用するのは非常に危険であることを意味します。そのためには、ラップしてください。

shared_ptrからへの変換unique_ptrは、前述のとおり、一般的な操作としてはサポートされていません。所有権の共有は、所有権の譲渡と直接互換性がないためです。ただし、合併症を無視すると。スレッド セーフは、単一の所有者(つまり、インスタンス)shared_ptr::uniqueが存在するかどうかを示します。その後、イニシャルがどのように構築されたかについて必要な知識があれば、free 関数を使用して削除関数へのポインターを取得し、次のことを実行できます。いくつかの低レベルの悪ふざけ。ここで私が話していることを完全に理解しているなら、それで結構です。そうでない場合は、これ以上詳細を説明しないことをお勧めします。これは非常に特殊なケースであり、細心の注意が必要であり、自分が何をしているのかを本当に知っている必要があるためです。;-)shared_ptrget_deleter

まあ、それはそれについてです。weak_ptr機能の一部にすぎないため、これについては説明しませんshared_ptr。しかし、うまくいけば、上記はあなたが求めているものです。

于 2010-11-21T09:45:28.400 に答える
2
  1. scoped_ptrAFAIK は TR1 の一部ではありません (間違っていたら訂正してください)。通常、 は所有権をまったく譲渡できませんboostscoped_ptrポインタを割り当てたら、それを解放することはできません。
  2. unique_ptrを使用してのみ所有権を譲渡できるstd::moveため、所有権も譲渡しません。
  3. shared_ptr他のポインターが所有権を共有している可能性があるため、所有権を解放することはできません。に変換できますweak_ptr。それを変換しようとしてweak_ptr、オブジェクトが解放された場合、それはスローされます。
  4. weak_ptrから作成できますがshared_ptr、に変換するshared_ptrと、オブジェクトが存在しなくなった場合にスローされる可能性があります。
于 2010-11-21T08:55:40.383 に答える