weak_ptrクラステンプレートはshared_ptrがすでに管理している オブジェクトへの「弱参照」を所有する。オブジェクトにアクセスするに weak_ptrは、 shared_ptr constructor か make_shared関数によって、shared_ptrに変換する ことができる。最後のshared_ptrが廃棄され、オブジェクトが削除されたら、 削除されたオブジェクトを参照するweak_ptrの実体から shared_ptrを得ようとすると失敗するだろう。 コンストラクタはboost::use_const_is_zero型の例外を投げ、 make_shared関数はデフォルトのコンストラクタで構築された (nullの)shared_ptrを返す。
全てのweak_ptrはC++標準ライブラリのCopyConstructibleと Assignableの要求を満たしているので標準ライブラリコンテナで使うことができる。 比較演算子が提供されているのでweak_ptrは標準関数の 連想コンテナで使うことができる。
クラステンプレートはテンプレートパラメータTをもつ。これは指される オブジェクトの型である。Tはスマートポインタの common requirementsを 満たしていなければならない。
shared_ptrに比べて、weak_ptrは 限られたサブセットの操作しか提供しない。これは、マルチスレッドプログラムで、 所有するポインタにアクセスすることはたいてい危険であり、また時々、 シングルスレッドプログラムの中でも安全ではないからである。 (つまり未定義の動作を引き起こしてしまうのだ。)例えば、次のような 不完全なプログラムの一部を考えてみよう:
shared_ptr<int> p(new int(5)); weak_ptr<int> q(p); // some time later if(int * r = q.get()) { // use *r }
ifのあと、rが使われる直前に
別のスレッドがp.reset()
ステートメントを実行することを
考えてみよう。今、rはダングリングポインタである。
(※訳注:ダングリングポインタ(dangling pointer)とは何をさしているか分からないポインタのこと)
この問題を解決する方法は、qから一時的な shared_ptrを作ることである。
shared_ptr<int> p(new int(5)); weak_ptr<int> q(p); // some time later if(shared_ptr<int> r = make_shared(q)) { // use *r }
ここではrはqが指すポインタへの参照を持っている。
もしp.reset()
が別のスレッドで実行されても、オブジェクトは
rがスコープの外に出てしまう(或いはresetされてしまう)まで
生きたままである。
namespace boost { template<typename T> class weak_ptr { public: typedef T element_type; weak_ptr(); template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws ~weak_ptr(); // never throws weak_ptr(weak_ptr const & r); // never throws template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws weak_ptr & operator=(weak_ptr const & r); // never throws template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws void reset(); T * get() const; // never throws; deprecated, will disappear long use_count() const; // never throws bool expired() const; // never throws void swap(weak_ptr<T> & b); // never throws }; template<typename T, typename U> bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T, typename U> bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T> bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws template<typename T> shared_ptr<T> make_shared(weak_ptr<T> const & r); // never throws }
typedef T element_type;
テンプレートパラメータの型Tを与える
weak_ptr();
Effects:weak_ptrをコンストラクトする。
Postconditions: use countは0。 所有するポインタは0。
Throws: std::bad_alloc.
Exception safety:例外が投げられると、コンストラクタは何もしない。
Notes: Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws
Effects: weak_ptrをコンストラクトし、rが所有するポインタの コピーを持つ。
Throws: なし。
Notes: 全てのコピーに対してuse countは変更されない 最後のshared_ptrが破棄されるとき、use countと所有するポインタは0になる。
weak_ptr(weak_ptr const & r); // never throws template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
Effects: weak_ptrをコンストラクトし、rが所有するポインタのコピーを 持つ。
Throws: なし.
Notes: 全てのコピーに対して use countは変更されない。
~weak_ptr(); // never throws
Effects: このweak_ptr を破棄するが、所有するポインタが指す オブジェクトには何も影響しない。
Throws: なし.
Notes: Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
weak_ptr & operator=(weak_ptr const & r); // never throws template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
Effects:
weak_ptr(r).swap(*this)
と等価.Throws: なし.
Notes: 効果(と保証)を満たす限り実装は自由である。一時的オブジェクトが作られることはない。
void reset();
Effects:
weak_ptr().swap(*this)
と等価.
T * get() const; // never throws
Returns: 所有するポインタ(そのポインタのための全ての shared_ptr オブジェクトが破棄されていれば0)
Throws: なし.
Notes: マルチスレッドのコードで get を使うのは危険である。 関数から戻った後、指しているオブジェクトを別のスレッドが破棄してしまうかもしれない。 weak_ptrはそのuse_countを変更しないからである。
[get は非常にエラーを起こしやすい。 シングルスレッドのコードでも、例えば指されたオブジェクトのメンバ関数によって 間接的に、getが返すポインタが無効にされているかもしれない。
get は非難されているし、将来のリリースでは無くなるだろう。 決してこれを使わないこと。]
long use_count() const; // never throws
Returns: 所有するポインタを共有するshared_ptrオブジェクトの数
Throws: なし.
Notes:
use_count()
は必ずしも効率的ではない。 デバッグとテストの目的でのみ使い、製品コードでは使わないこと。 Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
bool expired() const; // never throws
Returns:
use_count() == 0
.Throws: なし.
Notes:
expired()
はuse_count()
より 速いかもしれない。 Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
void swap(weak_ptr & b); // never throws
Effects: ふたつのポインタの内容を入れ替える。
Throws: なし.
Notes: Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
template<typename T, typename U> bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T, typename U> bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
Returns:
a.get() == b.get()
.Throws: なし.
Notes: Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
template<typename T> bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
Returns: an implementation-defined value such that operator< is a strict weak ordering as described in section 25.3
[lib.alg.sorting]
of the C++ standard.Throws: なし.
Notes: weak_ptr オブジェクトが連想コンテナのキーとして 使われることを許す。Tは完全な型である必要はない。スマートポインタの common requirementsを参考にせよ。
template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) // never throws
Effects:
a.swap(b)
と等価.Throws: なし.
Notes: std::swap インタフェースと同じ。 ジェネリックプログラミングを助けるだろう。
template<typename T> shared_ptr<T> make_shared(weak_ptr<T> & const r) // never throws
Returns:
r.expired()? shared_ptr<T>(): shared_ptr<T>(r)
.Throws: なし.
[make_shared の現在の実装は shared_ptr のデフォルトコンストラクタでの例外を転送することができるので、 明示された要求を満たしていない。 将来のリリースではこのデフォルトコンストラクタは例外を投げないだろう。]
Revised 29 August 2002
Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 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.