なぜ intrusive_ptr より shared_ptr をデフォルトとするべきか

http://thread.gmane.org/gmane.comp.lib.boost.devel/140434/
shared_ptr は, free store 上に参照カウント(と動的な削除子)を保持するオブジェクトを余分に必要とするので,基本的に(時間的・空間的)パフォーマンスとしては intrusive_ptr に劣る.なので, intrusive_ptr のほうが自然なんじゃないかと考える人が多いのだけれど,それに関する議論.
普通は intrusive_ptr が自然だと思われるのに shared_ptr があえてデフォルトとして推奨されているのには,なんらかの rationale があるはず. Peter Dimov 氏(個人的にスマートポインタのスペシャリストだと思っている人)による説明が以下.オレオレ的ちょーてきとー訳付き.
http://thread.gmane.org/gmane.comp.lib.boost.devel/140434/focus=140617


One reason for the "try shared_ptr first" recommendation is that while intrusive_ptr's advantages are usually obvious to developers, its disadvantages and shared_ptr's advantages are not. They became evident at a later date.

「shared_ptr をまず試してみろ」とお勧めする理由の1つとして, intrusive_ptr の利点が開発者に明らかである一方で, intrusive_ptr の不利な点と shared_ptr の利点はそうでない,ということが挙げられる.これらは後々明らかになったことである.

intrusive_ptr is obviously the right choice when (1) shared_ptr's overhead is unacceptable, (2) when the design often needs to convert raw pointers into smart pointers, (3) when the underlying API already uses intrusive counting.

intrusive_ptr は (1) shared_ptr のオーバーヘッドが受け入れられないとき,(2) 設計として生のポインタを頻繁にスマートポインタへ変換することが必要となるとき,(3)基づいている API がすでに侵入カウントを用いているとき,以上の場合にはまったくもって正しい選択である.(個人的な注:(2)は intrusive_ptr と比べた場合の shared_ptr の時間的なオーバーヘッドの大部分が,生ポインタからスマートポインタを生成するときに発生するという事実を暗黙の前提としているものと思われる)

And, if you pay attention:



>> "As a general rule, if it isn't obvious whether intrusive_ptr better
>> fits your needs than shared_ptr, try a shared_ptr-based design



you'll see that the recommendation is for the cases where it isn't obvious whether intrusive_ptr is a better choice.

で,注意してもらえれば分かるのだが




この推奨事項は intrusive_ptr を選択したほうが良いのかどうかが明らかでない場合に対するものである.

Since most programmers are naturally biased in favor of intrusive_ptr, this just balances the things out.

普通,ほとんどのプログラマは intrusive_ptr を好む傾向にあるので,こういう推奨を書いておくことによってその傾向に対するバランスを取っている.

The main disadvantage of intrusive_ptr is that you need to know about the reference count, which usually means no incomplete classes, and virtual inheritance from a non-abstract class containing data members in every interface. This is manageable, but if you can live without it, you'll certainly want to. Also, weak pointers are cool. Really.

intrusive_ptr の主な欠点は参照カウントの詳細について知る必要があるということだ.これは普通不完全クラスを取り扱えないことを意味するし,かつ全てのインターフェースにおいてデータメンバを持つ非抽象クラスからの仮想継承が必要になることを意味する.このような設計も可能だが,もしこういう手間無しにできるとすれば,当然そういう手間なしで済ませたいはずである.また weak pointer も素晴らしい.いやホントに.

最後に書いてあるように intrusive_ptr は不完全型に対応できないのだけれども,これはつまり以前述べたような不完全型と shared_ptr の組み合わせによる利用ができないことを意味する.確かにこういった intrusive_ptr の欠点はそれなりに経験がないとなかなか気付きにくい欠点だろうから,「まず最初に shared_ptr を試してみろ」という指針は(特に経験の浅いプログラマにとって)十分有用だと思われる.ただし,個人的にはこういうこともドキュメントにはっきり記述するべきだと思うんだけどにゃー. David Abrahams 氏も指摘してるけれど.こういう設計に対する細かい rationale の記述は,単に設計に対する説得材料としてだけではなくて,使う側の学習材料として非常に効果的という意味でも重要だと思うんだけれど.少なくともこの記事書いてる本人は,実際 Peter Dimov 氏のレス読んでへぇ〜へぇ〜,ためになるにゃーって感心してるし.
あと,個人的に "weak pointers are cool" という文言,確かに自分も cool だと思うけれど, weak_ptr を用いた設計のパターンって探しても探してもなっかなか出てこないから, weak_ptr が使えたらうれしいっつーのがなかなか実感として沸いてこないんだよにゃー.単にキャッシュとかそういうのだけじゃなくてもっと他にないのかにゃー.あと,オブジェクトの生存期間管理における poll-based と notification-based の比較とか,深い議論があったら絶対面白いと思うんだけれど.