2016-04-25 17 views
4

私は弱いポインタを理解するためのニコライM. Josuttis氏による「C++標準ライブラリ」本を読んでいました。著者はweak_ptrを持つ必要性の理由を2つ挙げましたが、第2の理由はありません。誰でも簡単な説明と以下の理由の例を挙げることができます(本から引用):C++ 11でweak_ptrが必要なのはなぜですか?

もう1つの例は、明示的に共有するがオブジェクトを所有しない場合に発生します。したがって、オブジェクトへの参照の存続期間が参照するオブジェクトよりも寿命が長いというセマンティクスがあります。ここで、shared_ptrsはオブジェクトを決して解放せず、通常のポインタはそれらが参照するオブジェクトがもはや有効でないことに気付かず、解放されたデータにアクセスする危険性がある。そして、あなたがしたい - ポインタがポインタを所有でない場合、それはどのようなソフトウェアによって削除される可能性がありますを指しているオブジェクトが所有者である:

+3

共有所有権で作成されたオブジェクトのキャッシュを想像してみてください。オブジェクトを不必要に生存させたくないのですが、実際にはまだ生きている限り、キャッシュはオブジェクトに対するハンドルを取得する方法を提供します。 –

+0

これは[link](http://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful)助けてくれるかもしれません –

+0

実際には、恐らく本が弱いポインタのために与えた_first_理由それはキャッシュだと思われますが、そうでないかもしれません。 – davidbak

答えて

8

その文の後半は明らかです標準的な参照があります。

この問題は、他のソフトウェアにアクセスできるようにするソフトウェアによってオブジェクトが所有されていることです。他のソフトウェアではは共有されません。したがって、所有者はいつでも削除することができ、他のソフトウェアはポインタがもはや有効ではないことを知る必要があります。

たぶん例が役立つだろう:

をあなたは鳥の餌箱にあなたの窓の外を指して、カメラを見ているソフトウェアのいくつかの作品を持っているし、それが行ったり来たりフィーダーに鳥を、識別されます。フィーダーの各鳥は、フィーダーに到着したときにこのソフトウェアで作成されたオブジェクトを持ち、鳥が飛んできたらオブジェクトを削除します。

一方、他のいくつかのソフトウェアは、それは国勢調査を取ります。 10秒ごとに、フィーダの監視ソフトウェアからフィーダの鳥のコレクションが取得されます。 100秒ごとに、100秒間にわたって鳥がフィーダーにいた報告が出されます。

鳥のデータが大きいため、国勢調査はコピーのデータはありません。それは単に、10秒ごとに、フィーダーウォッチャーからポインタのコレクションを取得します。

は、それが必要なのは、フィーダーウォッチャーは、最後の10秒があった、ないものに到着した鳥へのポインタを提供して言わせて、弱いポインタを使用できるようにすること。つまり、鳥が姿を消したという通知はありません。

まだそこにいる鳥のいる、レポートの時点で、それは知ることができ、弱いポインタを使用することにより

、彼らが到着したとき(しかし、彼らは残っていません)。

(たぶん私は、後に、より良い例を考えましょう。)

4

は、上記の例では架空のタイマーイベントソース

struct my_thing : std::enable_shared_from_this<my_thing> 
{ 
    void start() 
    { 
    auto weak_self = std::weak_ptr<my_thing>(shared_from_this()); 
    _timer.set_callback([weak_self] { 
     if (auto self = weak_self.lock()) { 
     self->respond_to_timer(); 
     } 
    }); 
    } 

    void respond_to_timer() 
    { 
    // do something here 
    } 

    SomeTimer _timer; 
}; 

にコールバック関数を想像my_thingは、タイマーを所有しているが、タイマーにはmy_thingを参照するコールバックが与えられています。これは、my_thingが削除されるのを防ぐ循環参照になります。

巡回所有権の問題を破るのweak_ptr weak_selfの使用。

+0

'my_thing'が実際にタイマーを所有している場合、コールバックにプレーンポインタを使用するだけではどうですか? –

+3

@KerrekSBイベントがタイマーのディスパッチャーにある間に 'my_thing'が削除された可能性があるためです。 weak_ptrをロックするアクションは、デリゲートオブジェクトが存在することを証明し、コールバック中にそのオブジェクトを有効にします。これは、マルチスレッドソリューションでは特に重要です。 –

+0

'my_thing'が削除された場合、' _timer'も含まれていましたね。 –

2

例えば:この例では

struct node 
{ 
    std::shared_ptr<node> left_child; 
    std::shared_ptr<node> right_child; 
    std::weak_ptr<node> parent; 
    foo data; 
}; 

、ノードを削除するleft_childとright_childではなく、親が消去されます。なんらかの理由でノードが親よりも長く張り付いて親が削除された場合、親がもう有効ではないことを知る方法があります。 (別のshared_ptrでleft_childまたはright_childを参照していないと仮定して)

+0

良い例ですが、 "ノードを削除すると、' left_child'と 'right_child'" * - が消去されます。これは 'unique_ptr'に当てはまります。 'shared_ptr'のために、それらを消去するかもしれません。 –

+1

さて、あなたは物事への共有ポインタを1つだけ持っていると仮定すると本当です。しかし、unique_ptrはweak_ptrをサポートしていません。 – Exaeta

関連する問題