c++boost.gif (8819 bytes)weak_ptr class template

Introduction
Synopsis
Members
Free Functions
Frequently Asked Questions

Introduction

weak_ptr クラステンプレートは、既に shared_ptr により管理されているオブジェクトへの "弱参照" を保持する。 shared_ptr のコンストラクタ を利用して weak_ptrshared_ptr に変換するか、 メンバ関数 lock を使うことで、 保持しているオブジェクトにアクセスできる。 所有権を共有している最後の shared_ptr が破棄され、 保持しているオブジェクトが削除された場合、 その削除済みのオブジェクトを参照する weak_ptr インスタンスを shared_ptr へと変換する試みが失敗する: 変換コンストラクタは boost::bad_weak_ptr 例外を送出し、 weak_ptr::lock空の shared_ptr を返す。

weak_ptr は C++標準ライブラリのコピーコンストラクト可能(CopyConstructible) および代入可能(Assignable)の要求を満たしているので、 標準ライブラリコンテナに格納することができる。 また、比較演算子が提供されているので標準の連想コンテナに格納することができる。

weak_ptr命令は例外を送出しない。

このクラステンプレートには、指し示すオブジェクトの型を表すパラメータ T を与える。

weak_ptr に保持されているポインタへのアクセスは マルチスレッドプログラムにおいてしばしば危険にさらされるため、 weak_ptr が提供する命令は shared_ptr が提供する命令と比較して、 制限が大幅に強化されたサブセットとなっている。 また、シングルスレッドプログラムにおいても、安全と言い切れない場面がある (それは未定義のふるまいを引き起こす)。 ここで、weak_ptr に生ポインタを返すメンバ関数 get() があるとして、次の悪意のないコードについて考えてみよう:

shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);

// その少し後で

if(int * r = q.get())
{
    // *r を使う
}

if の後、且つ r が使われる直前に、別のスレッドが p.reset() という文を実行することを考えてみよう。 その時点で、r はダングリングポインタになってしまう (※訳注:ダングリングポインタ(dangling pointer)とは、何を指しているかわからないポインタのこと)

この問題を解決する方法は、q から一時的な shared_ptr を作成することである:

shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// その少し後で

if(shared_ptr<int> r = q.lock())
{
    // *r を使う
}

ここでは、rq に指されたオブジェクトを参照している。 もし p.reset() が別のスレッドで実行されても、参照されているオブジェクトは r がスコープを抜けるかリセットされるまで生存し続ける。 そのオブジェクトを指す shared_ptr を作ることで、 事実上そのオブジェクトの破棄に対するロックを掛けることができる。

Synopsis

namespace boost {

  template<class T> class weak_ptr {

    public:
      typedef T element_type;

      weak_ptr();

      template<class Y> weak_ptr(shared_ptr<Y> const & r);
      weak_ptr(weak_ptr const & r);
      template<class Y> weak_ptr(weak_ptr<Y> const & r);

      ~weak_ptr();

      weak_ptr & operator=(weak_ptr const & r);
      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);

      long use_count() const;
      bool expired() const;
      shared_ptr<T> lock() const;

      void reset();
      void swap(weak_ptr<T> & b);
  };

  template<class T, class U>
    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);

  template<class T>
    void swap(weak_ptr<T> & a, weak_ptr<T> & b);
}

Members

element_type

typedef T element_type;

テンプレートパラメータ T の型を提供する。

constructors

weak_ptr();

Effects: 空(empty)の weak_ptr を構築する。

Postconditions: use_count() == 0

Throws: 無し。

template<class Y> weak_ptr(shared_ptr<Y> const & r);
weak_ptr(weak_ptr const & r);
template<class Y> weak_ptr(weak_ptr<Y> const & r);

Effects: もし r空(empty)ならば、 空(empty)の weak_ptr を構築する; そうでなければ、まるで r が持つポインタのコピーを持ち合う様に r所有権を共有する weak_ptr を構築する。

Postconditions: use_count() == r.use_count()

Throws: 無し。

destructor

~weak_ptr();

Effects: その weak_ptr を破棄する。 指されているオブジェクトには何も作用を及ぼさない。

Throws: 無し。

assignment

weak_ptr & operator=(weak_ptr const & r);
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);

Effects: weak_ptr(r).swap(*this) と等価。

Throws: 無し。

Notes: 実際の実装は、上記とは異なる表現により、 一時オブジェクトを作成せずに上記のコードと同様の作用(effects)と保証を得る。

use_count

long use_count() const;

Returns: もし *this空(empty)ならば、 不特定の非負の数; そうでなければ、*this所有権を共有する shared_ptr オブジェクトの数。

Throws: 無し。

Notes: use_count() は必ずしも効率的なものではない。 デバッグやテスト目的でのみ使い、製品のコードには使わないこと。

expired

bool expired() const;

Returns: use_count() == 0

Throws: 無し。

Notes: expired()use_count() よりも速いかもしれない。

lock

shared_ptr<T> lock() const;

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

Throws: 無し。

リセット (reset)

void reset();

Effects: weak_ptr().swap(*this) と等価。

交換 (swap)

void swap(weak_ptr & b);

Effects: 二つのスマートポインタの内容を入れ替える。

Throws: 無し。

非メンバ関数 (Free Functions)

比較 (comparison)

template<class T, class U>
  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);

Returns: 以下に示すような明示的でない値。

Throws: 無し。

Notes: weak_ptr オブジェクトを連想コンテナのキーとして使えるようにするための演算子。

swap

template<class T>
  void swap(weak_ptr<T> & a, weak_ptr<T> & b)

Effects: a.swap(b) と等価。

Throws: 無し。

Notes: std::swap とのインターフェースの共通化を図り、 ジェネリックプログラミングを支援する。

Frequently Asked Questions

Q. コンストラクタの中で、自身を指す weak_ptr を作成するオブジェクトを作れますか?

A. いいえ、できません。 weak_ptrshared_ptr からのみ作成する事ができるのですが、オブジェクトを構築する時点では、そのオブジェクトを指す shared_ptr はまだ存在しないでしょう。 例え this を指す一時的な shared_ptr を作成したとしても、コンストラクタのスコープを抜けた時点でその shared_ptr インスタンスは破棄されてしまい、 全ての weak_ptr インスタンスは即座に期限切れ(expire)になってしまいます。

この質問に対する解決策は、コンストラクタをプライベートにし、 shared_ptr を返すファクトリ関数を提供することです:

class X
{
private:

    X();

public:

    static shared_ptr<X> create()
    {
        shared_ptr<X> px(new X);
        // ここで px から弱参照ポインタ(weak_ptr)を作成する
        return px;
    }
};



$Date: 2003/09/02 06:19:54 $

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002, 2003 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.

Japanese Translation Copyright (C) 2003 Ryo Kobayashi, Kohske Takahashi.
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の 複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」 に提供されており、いかなる明示的、暗黙的保証も行わない。また、 いかなる目的に対しても、その利用が適していることを関知しない。