スマートポインタweak_ptrをブースト



Boost Smart Pointer Weak_ptr



循環参照

参照カウントは便利なメモリ管理メカニズムですが、周期的に参照されるオブジェクトを管理できないという大きな欠点があります。簡単な例は次のとおりです。



#include #include #include #include class parent class children typedef boost::shared_ptr parent_ptr typedef boost::shared_ptr children_ptr class parent { public: ~parent() { std::cout <<'destroying parent ' } public: children_ptr children } class children { public: ~children() { std::cout parent = father } void main() { std::cout<<'begin test... ' test() std::cout<<'end test. ' }

プログラムを実行して、テスト関数を終了した後でも、親オブジェクトと子オブジェクトが相互に参照しているため、参照カウントが1であり、自動的に解放できず、現時点では2つのオブジェクトにアクセスできないことを確認します。これにより、C ++で悪名高いメモリリークが発生しました。

一般に、この循環参照を元に戻すには3つの方法があります。

  • 最後の参照のみが残っている場合は、オブジェクトを解放するために循環参照を手動で解除する必要があります。
  • 親の存続期間が子の存続期間を超える場合、子は代わりに通常のポインターを使用して親を指します。
  • 弱く参照されているスマートポインタを使用して、この循環参照を解除します。

3つの方法はすべて実行可能ですが、方法1と2はどちらもプログラマーによる手動制御が必要であり、面倒でエラーが発生しやすくなります。これは、3番目の方法とブーストのウィークポインターブーストの簡単な紹介です:boost :: weak_ptr。

強参照と弱参照

強い参照の場合、参照されたオブジェクトがまだ生きている場合、この強い参照が存在します(つまり、少なくとも1つの強い参照がある場合、オブジェクトを解放することはできません)。 Boost :: share_ptrは強力なリファレンスです。

相対的に言えば、弱参照の場合、参照オブジェクトが生きているときに弱参照が必ずしも存在するとは限りません。存在する場合の単なる参照。弱参照はオブジェクトの参照カウントを変更しません。つまり、この弱参照はオブジェクトのメモリを管理せず、通常のポインタと機能が似ています。ただし、大きな違いは、弱参照が管理対象オブジェクトを検出できることです。解放されたかどうか。したがって、不正なメモリへのアクセスを回避します。

boost :: weak_ptr

Boost :: weak_ptrは、boostによって提供される弱く参照されるスマートポインターです。その宣言は次のように簡略化できます。

namespace boost { template class weak_ptr { public: template weak_ptr(const shared_ptr& r) weak_ptr(const weak_ptr& r) ~weak_ptr() T* get() const bool expired() const shared_ptr lock() const } }

ご覧のとおり、boost :: weak_ptrは1つのboost :: shared_ptrまたは別のboost :: weak_ptrから変換する必要があります。これは、オブジェクトのメモリ管理が強く参照されているboost :: shared_ptrであることも示しています。 Boost :: weak_ptrは、管理対象オブジェクトにアクセスする手段を提供するだけです。

(get()関数を介した)管理対象オブジェクトへの基本的なアクセスに加えて、boost :: weak_ptrには2つの一般的に使用される関数関数があります。管理対象オブジェクトへの強力な参照ポインター。

boost :: weak_ptrで循環参照を壊す

弱参照は通常のポインターと同様に参照カウントを変更しないため、循環参照が使用するパーティへの弱参照を使用することで循環参照を削除できます。上記の例では、子の定義を次のように変更するだけで、循環参照を元に戻すことができます。

class children { public: ~children() { std::cout <<'destroying children ' } public: boost::weak_ptr parent }

最後に、ポインタを弱く参照することで循環参照を効果的に削除できますが、プログラマが循環参照の発生を予測できる場合はこのメソッドを使用する必要があります。そうしないと、これはコンパイル期間にすぎないと言えます。解決策として、実行中にプログラムに循環参照がある場合でも、メモリリークが発生します。したがって、スマートポインタを使用してメモリリークを排除できるとは思わないでください。結局のところ、C ++の場合、ガベージコレクションメカニズムがないため、メモリリークはすべてのプログラマーにとって大きな頭痛の種です。

元の住所: http://www.cnblogs.com/TianFang/archive/2008/09/20/1294590.html