2009-02-26 21 views
2

メモリ管理についてのいくつかの質問(herehere)を求めましたが、誰かがboost :: shared_ptrsを使用することを常に提案しています。Boost :: shared_ptrsを使用しない理由はありますか?

彼らはどれほど役に立つと思われるのですか、私は真剣にboost :: shared_ptrsを使用するようにアプリケーション全体を切り替えることを検討しています。

しかし、私は両足でジャンプしてこれをやる前に、誰かがboost :: shared_ptrsで悪い経験をしたことがありますか?私が注意する必要があるそれらを使用するいくつかの落とし穴ですか?

現時点では、私のガベージコレクションの懸案事項の大部分を自動的に処理することは、あまりにも真実に見えます。欠点は何ですか?

答えて

4

欠点は、無料ではないということです。 scoped_ptr/scoped_array(または普通の古いスタック割り当て)の場合は、特にshared_ptr/shared_arrayを使用しないでください。 weak_ptrがある場合は手動でサイクルを中断する必要があります。あなたがリンクしているベクトル質問は、私がshared_ptrに到達するかもしれない1つのケースです。私はそうではない第2の質問です。コピーしないことは時期尚早の最適化です。特に、文字列クラスが既にそれを行っている場合は特にそうです。文字列クラスが参照カウントされている場合、COWを正しく実装することもできますが、実際にはshared_ptr<string>のアプローチでは実行できません。 shared_ptr willy-nillyを使用すると、外部ライブラリ/ apisとの「インタフェース摩擦」も導入されます。

+0

文字列は通常COWを使用しません。マルチスレッドのアプリケーションではうまく動かないため、ほとんどの実装で再びその問題が解決されました。つまり、文字列のコピーには多少のコストがかかります。 – jalf

+0

GCCの文字列実装ではまだCOW IIRCが使用されています。しかし、C++ 0xの場合、これらはおそらく許可されません(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2668.htm)。 –

0

ダイナミックメモリオーバヘッド(すなわち、余分な割り当て)+参照カウントされたスマートポインタに関連するすべてのオーバーヘッド。

2

C++でのブースト共有ポインタやその他のメモリ管理手法は、万能薬ではありません。注意深いコーディングの代用はありません。 boost :: shared_ptrを使用すると、オブジェクトの所有権に注意し、循環参照を避けることができます。あなたは明示的にサイクルを中断するか、必要に応じてboost :: weak_ptrを使用する必要があります。

インスタンスが割り当てられてから、boost :: shared_ptrを常に使用するように注意してください。そうすれば、あなたはぶら下がっている参照がないと確信しています。これを確実にする方法の1つは、新しく作成されたオブジェクトをshared_ptrに返すファクトリメソッドを使用することです。

typedef boost::shared_ptr<Widget> WidgetPtr; 
WidgetPtr myWidget = Widget::Create(); 
1

私はしばしばshared_ptrを使用します。

Shared_ptrは値によってコピーされるため、ポインタ値と参照カウントの両方をコピーするコストがかかりますが、boost :: intrusive_ptrを使用すると参照カウントをクラスに追加する必要があります未処理のポインタを使用する場合に比べてオーバーヘッドはありません。

私の経験では、99%以上の時間で、コード全体にboost :: shared_ptrインスタンスをコピーするオーバーヘッドは重要ではありません。 C. A. R. Hoareが指摘するように、早すぎる最適化は無意味です。ほとんどの場合、他のコードは小さなオブジェクトをコピーする時間よりもかなり長い時間を使用します。あなたのマイレージは異なる場合があります。プロファイリングでコピーが問題であることが示されている場合は、侵入型のポインタに切り替えることができます。

前述のとおり、weak_ptrを使用してサイクルを分割する必要があります。そうしないとメモリリークが発生します。これはグラフなどのデータ構造で発生しますが、たとえば、リーフが後方を向くことのないツリー構造を作成している場合は、ツリーのノードに対してshared_pointersを問題なく使用できます。

shared_ptrを使用すると、コードが大幅に簡素化され、読みやすく、保守が容易になります。多くの場合、それらを使用するのが正しい選択です。

もちろん、すでに述べたように、場合によってはscoped_ptr(またはscoped_array)を使用するのが適切です。 pointeeが共有されていない場合は、共有ポインタを使用しないでください。

最後に、最近のC++標準ではstd :: tr1 :: shared_ptrテンプレートが提供されています。これは現在ほとんどのプラットフォーム上にありますが、tr1用の侵入型ポインタ型はないと思います私はそれを自分で聞いたことがありません)。

関連する問題