c++boost.gif (8819 bytes)Smart Pointers

スマートポインタは動的に割り当てられた(ヒープ上の)オブジェクトへのポインタを 保存するオブジェクトである。これは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が所有するオブジェクトを、所有しないで観察する。

これらのテンプレートはstd::auto_ptrテンプレートを補完するようにデザインされている。

これらは「資源獲得は初期化である」という格言の実例である。この格言は Bjarne Stroustrupの"The C++ Programming Language"第3版14.4章、資源管理の項で述べられている。

テストプログラムsmart_ptr_test.cppが 正しい操作を確認するために提供されている。

Boost smart pointerライブラリの古いバージョンについてのページ compatibilityは、 以前のバージョンのスマートポインタの実装からの変更について述べている。

smart pointer timings はパフォーマンスの 問題についての興味である。

Common Requirements

これらのスマートポインタクラステンプレートはテンプレートパラメータTをもつ。 これはスマートポインタが指すオブジェクトの方を特定する。 スマートポインタテンプレートの振る舞いは、T型のオブジェクトの デストラクタかdelete演算子が例外を投げるなら、未定義である。

Tはスマートポインタの宣言という点で、不完全な型かもしれない。 通常、Tはスマートポインタの実体化という点で完全な型である必要がある。 不完全な型の削除を含めて、この要求を脅かすこと全てを診断する(エラーとして扱う) ような実装が必要である。 checked_delete 関数テンプレートの記述を参考にせよ。

shared_ptrはこの制限を持たず、メンバ関数の多くはT が完全な型であることを要求しないことに注意せよ。

Rationale

Tへの要求は、安全性を最大化しつつ、扱いやすいように、という格言の下で 注意深く作られている。この格言の中ではスマートポインタは、 Tが不完全な型である翻訳単位の中で現れる。 これは実装とインタフェースを分離し、インタフェースが利用される翻訳単位から実装を隠す。 それぞれのスマートポインタについてのこのドキュメントでの例は、 このようなスマートポインタの利用を説明している。

scoped_ptrはTがデストラクト時に完全な型であることを要求するが、 shared_ptrはそうでないことに注意せよ。

Exception Safety

これらのスマートポインタクラスの多くの関数は、もし例外が投げられれば 「効果なし」あるいは「これこれ以外は効果なし」として明示されている。 これはこれらのクラスの一つのオブジェクトが例外を投げた時、プログラムの 状態全てが、結果的に例外を発生した関数が呼び出される前の状態と同じである ことを意味している。つまり発見しうる副作用がないことを保証している。 そうでない関数は決して例外を投げない。関数が投げる唯一の例外は std::bad_allocである(Tが common requirementsを満たしていることを仮定する)。 std::bad_allocを投げる可能性があると、明示的にドキュメントに書かれている 関数だけが、この例外を投げる。

Exception-specifications

Exception-specificationsは利用されない。 exception-specification rationaleを参考にせよ。

全てのスマートポインタテンプレートは決して例外を投げないメンバ関数を持っている。 決して例外を投げないというのは、自分自身に例外を投げることも、 例外を投げる他の関数を呼び出すこともないということである。 これらのメンバはコメント: //never throws と明示されている。

指されたオブジェクト型を破壊(destroy)する関数は common requirementsによって 例外を投げることを禁止されている。

History and Acknowledgements

January 2002. Peter Dimov reworked all four classes, adding features, fixing bugs, and splitting them into four separate headers, and added weak_ptr. See the compatibility page for a summary of the changes.

May 2001. Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.

November 1999. Darin Adler provided operator ==, operator !=, and std::swap and std::less specializations for shared types.

September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.

October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr and counted_ptr which were very similar to what we now call scoped_ptr and shared_ptr. The committee document was 94-168/N0555, Exception Safe Smart Pointers. In one of the very few cases where the Library Working Group's recommendations were not followed by the full committee, counted_ptr was rejected and surprising transfer-of-ownership semantics were added to auto_ptr.

Beman Dawes proposed reviving the original semantics under the names safe_ptr and counted_ptr at an October, 1998, meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar K�hl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four class names were finalized, it was decided that there was no need to exactly follow the std::auto_ptr interface, and various function signatures and semantics were finalized.

Over the next three months, several implementations were considered for shared_ptr, and discussed on the boost.org mailing list. The implementation questions revolved around the reference count which must be kept, either attached to the pointed to object, or detached elsewhere. Each of those variants have themselves two major variants:

Each implementation technique has advantages and disadvantages. We went so far as to run various timings of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar K�hl suggested an elegant partial template specialization technique to allow users to choose which implementation they preferred, and that was also experimented with.

But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose to supply only the direct implementation.


Revised 4 February 2002

Copyright 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.