Smart
PointersIntroduction
Common Requirements
Exception Safety
Exception-specifications
History and Acknowledgements
References
スマートポインタは動的に割り当てられた(ヒープ上の) オブジェクトへのポインタを保持するオブジェクトである。 これらは、指されたオブジェクトを適当なタイミングで自動的に削除する事を除いて、 C++ の組み込みポインタのように振る舞う。 スマートポインタは、動的に割り当てられたオブジェクトを、 例外が発生しても確実に破棄したいようなときに特に役立つ。 また複数の所有者に共有されている、 動的に割り当てられたオブジェクトを管理するのにも使える。
概念的にはスマートポインタは指されたオブジェクトを所有しているように見える。 そしてオブジェクトがもはや必要なくなった時、責任を持って削除する。
スマートポインタライブラリは5種類のスマートポインタのクラステンプレートを提供する:
| scoped_ptr | <boost/scoped_ptr.hpp> | オブジェクトの所有権を独占する単純なスマートポインタ。コピー不可。 |
| scoped_array | <boost/scoped_array.hpp> | 配列を独占的に所有する単純なスマートポインタ。コピー不可。 |
| shared_ptr | <boost/shared_ptr.hpp> | 複数のポインタでオブジェクトの所有権を共有するスマートポインタ。 |
| shared_array | <boost/shared_array.hpp> | 複数のポインタで配列の所有権を共有するスマートポインタ。 |
| weak_ptr | <boost/weak_ptr.hpp> | shared_ptr が所有するオブジェクトを所有せずにアクセスするスマートポインタ。 |
| intrusive_ptr | <boost/intrusive_ptr.hpp> | 埋め込まれた参照カウントによって所有権を共有するスマートポインタ。 |
これらのテンプレートは std::auto_ptr テンプレートを補完するように設計されている。
これらは " Resource Acquisition Is Initialization " イディオム (訳注:RAIIイディオム、「資源獲得を初期化時に行う」ことによりオブジェクトの所有権の所在を明確にする) の典型例である。 このイディオムは Bjarne Stroustrup の "The C++ Programming Language" 第 3 版 14.4 章、資源管理の項で述べられている。
テストプログラム smart_ptr_test.cpp が、スマートポインタの動作確認のために提供されている。
Boost smart pointer ライブラリの古いバージョンについてのページ compatibility は、 以前のバージョンのスマートポインタの実装からの変更について述べている。
smart pointer timings はスマートポインタの パフォーマンスについての説明である。
これらのスマートポインタのクラステンプレートはテンプレートパラメータ T をもつ。 これはスマートポインタが指すオブジェクトの型を特定する。 スマートポインタの振る舞いは、T 型のオブジェクトの デストラクタまたは delete 演算子 が例外を送出する場合は未定義である。
スマートポインタの宣言の時点では T に不完全型を指定することもできる。 しかし、スマートポインタの実体化の観点から見ると、T は完全型でなくてはならない。 不完全型の削除を含めて、この要求を脅かすこと全てを診断する(エラーとして扱う) ような実装が必要である。 checked_delete 関数テンプレートの記述を参考にせよ。
shared_ptr はこの制限を持たず、メンバ関数の多くは T が完全な型であることを要求しないことに注意せよ。
T への要求は、handle-body (別名 pimpl) イディオムやそれに準ずる用法において、 最大限の安全性を提供できるように注意深く設計されている。 これらの用法において、スマートポインタは T が不完全型である翻訳単位の中で使用される。 handle-body イディオムは、実装とインタフェースを分離し、 インタフェースが利用される翻訳単位から実装を隠す。 これらの用法におけるスマートポインタの使い方の例が、 それぞれのスマートポインタのドキュメントにて説明されている。
scoped_ptr は T がデストラクト時に完全な型であることを要求するが、 shared_ptr はそうでないことに注意せよ。
これらのスマートポインタクラスの多くの関数は、もし例外が投げられれば 「効果なし」あるいは「これこれ以外は効果なし」として明示されている。 これはこれらのクラスの一つのオブジェクトが例外を投げた時、プログラムの 状態全てが、結果的に例外を発生した関数が呼び出される前の状態と同じである ことを意味している。つまり発見しうる副作用がないことを保証している。 そうでない関数は決して例外を投げない。関数が投げる唯一の例外は std::bad_alloc である( T が common requirements を満たしていることを仮定する)。 ドキュメントに明示的に std::bad_alloc を投げる可能性があると記されている関数だけが、この例外を投げる。
例外仕様は利用されない。 exception-specification rationale を参考にせよ。
全てのスマートポインタテンプレートは決して例外を投げないメンバ関数を持っている。
決して例外を投げないというのは、自分自身に例外を投げることも、
例外を投げる他の関数を呼び出すこともないということである。
これらのメンバはコメント: //never throws と明示されている。
指されたオブジェクト型を破壊(destroy)する関数は common requirements によって 例外を投げることを禁止されている。
2002 年 1 月。 Peter Dimov により 4 つのクラスの全てが作り直された。 機能の追加とバグの修正が行われ、 それぞれのクラスが 4 つのヘッダファイルに分割された。 weak_ptr が追加された。 変更箇所については 互換性 のページを参照せよ。
2001 年 5 月。 Vladimir Prus により、デストラクト時における完全型の必要性が提案された。 Dave Abrahams、Greg Colvin、Beman Dawes、Rainer Deyke、Peter Dimov、John Maddock、Vladimir Prus、Shankar Sai 等を含めて行われた 評議により、改善策が導き出された。
1999 年 11 月。 Darin Adler により、共有スマートポインタ型の為の operator ==、operator !=、及び std::swap、std::less の特殊化版が提供された。
1999 年 9 月。 Luis Coelho により、 shared_ptr::swap と shared_array::swap が提供された。
1999 年 4 月。 1999 年の 4 月、5 月に、 Valetin Bonnard と David Abrahams により 非常に多くの改善点についての提案が為される。
1998 年 10 月。 1994 年に Greg Colvin により、C++ 標準化委員会にクラス auto_ptr とクラス counted_ptr が提案された。 counted_ptr は、現在の scoped_ptr や shared_ptr とほぼ同様のものである。 標準ドキュメントの 94-168/N0555、例外安全スマートポインタ(Exception Safe Smart Pointers) の項に当たる。 委員会によりライブラリワーキンググループの勧告が否決された数少ない事例の一つとして counted_ptr は棄却され、所有権の譲渡のセマンティクスは驚くべき事に auto_ptr に追加された。
1998 年の 10 月に行われた、 Per Andersson、Matt Austern、Greg Colvin、Sean Corfield、 Pete Becker、Nico Josuttis、Dietmar K?l、Nathan Myers、 Chichiang Wan、Judy Ward 等による会議に於いて、 Beman Dawes により 当初のセマンティクスを safe_ptr と counted_ptr という名前で復活させることが提案された。 議論の中で、4 つのクラスの名前が決定され、 std::auto_ptr のインターフェースに厳密に準拠する必要はないという結論に達した。 そして、それぞれの関数のシグネチャとセマンティクスが決定された。
その後の 3 ヶ月以上、shared_ptr のために幾つかの実装が熟考され、 boost.org のメーリングリストで議論された。 実装に関する議論では、参照カウントの実装方法について繰り返し論じられた。 参照カウントをスマートポインタに指されるオブジェクトに結びつけて管理する方法と、 指されるオブジェクトとは別に管理する方法のいずれに於いても、 参照カウントの値が保持されなければならない。 そのためには、それぞれの方法に対し大きく分けて二つの実装が考えられた。
上に挙げた全ての実装に長所と短所がある。 そこで我々は、直接的及び間接的なアプローチで様々なタイミングのテストを行った。 その結果、Intel Pentium のCPUにおいて、僅かではあるが測定可能な性能差を検出できた。 Kevlin Henney は彼の論文 "Counted Body Techniques" にてこの事を述べている。 Dietmar Kühl はテンプレートの部分特殊化を利用したエレガントな 実装の切り替え技術を提案し、また実験した。 これは、ライブラリのユーザの好みに応じてその実装を切り替えるという 技術である。
しかし Greg Colvin と Jerry Schwarz は「ライブラリのパラメータ化はユーザを敬遠させる」と反論し、 最終的に我々は直接的な実装を採用することに決定した。
1994 年の夏、Greg Colvin は C++ 標準化委員会に auto_ptr クラス及び counted_ptr クラスを提案した。 counted_ptr は、現在の scoped_ptr や shared_ptr によく似たものである。 [Col-94] しかし、counted_ptr は不採用になり、 驚くべき事に auto_ptr に所有権を譲渡するセマンティクスが追加された。 これは、ライブラリのワーキンググループの勧告が、 全委員会での支持を得られなかった数少ないケースの一つである。
[Col-94] Gregory Colvin, Exception Safe Smart Pointers (例外安全スマートポインタ), C++ committee document 94-168/N0555, 1994年7月。
[E&D-94] John R. Ellis & David L. Detlefs, Safe, Efficient Garbage Collection for C++ ( C++における安全で効率的なガベージコレクション ), Usenix Proceedings, 1994年2月。 この論文は、ウィークポインタに関する詳細な考察と、文献目録を含む。
$Date: 2003/08/19 14:15:50 $
Copyright (C) 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. 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
Kohske Takahashi,
Ryo Kobayashi.
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の
複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」
に提供されており、いかなる明示的、暗黙的保証も行わない。また、
いかなる目的に対しても、その利用が適していることを関知しない。