weak_ptr

weak_ptrは、C++11で導入されたスマートポインタの一種で、参照はできるが、リソースの所有権を持つことはできない。

weak_ptr - cpprefjp C++日本語リファレンス

class_testの中で、子オブジェクトポインタptr_がshare_ptrの場合に、まず、main.cppで、

// ヘッダのインクルード
// 独自のヘッダ
#include "test.h" // クラスclass_test
// 既定のヘッダ
#include <iostream> // 標準入出力
#include <memory> // メモリ管理

// main関数
int main(){

  // share_ptrの生成.
  std::shared_ptr<class_test> p1(new class_test(10)); // class_testオブジェクトポインタをshared_ptrのp1に渡す.
  std::shared_ptr<class_test> p2(new class_test(20)); // class_testオブジェクトポインタをshared_ptrのp2に渡す.
  std::shared_ptr<class_test> p3(new class_test(30)); // class_testオブジェクトポインタをshared_ptrのp3に渡す.

  // 子ポインタをp3にする.(この場合は, p1からp3までの全てのデストラクタが呼ばれる.)
  p1->ptr_ = p3; // p1->ptr_にp3をセット.
  p2->ptr_ = p3; // p2->prt_にp3をセット.

  // プログラムの終了.
  return 0; // 0を返して正常終了.

}

こうすると、

$ vi main.cpp 
$ g++ -o main main.cpp test.cpp -std=c++11
$ ./main 
class_test::class_test(10)
class_test::class_test(20)
class_test::class_test(30)
class_test::~class_test()
class_test::~class_test()
class_test::~class_test()
$

すべてのデストラクタが呼ばれるのでこうなる。

次に、

// ヘッダのインクルード
// 独自のヘッダ
#include "test.h" // クラスclass_test
// 既定のヘッダ
#include <iostream> // 標準入出力
#include <memory> // メモリ管理

// main関数
int main(){

  // share_ptrの生成.
  std::shared_ptr<class_test> p1(new class_test(10)); // class_testオブジェクトポインタをshared_ptrのp1に渡す.
  std::shared_ptr<class_test> p2(new class_test(20)); // class_testオブジェクトポインタをshared_ptrのp2に渡す.
  //std::shared_ptr<class_test> p3(new class_test(30)); // class_testオブジェクトポインタをshared_ptrのp3に渡す.

  // 子ポインタをp3にする.(この場合は, p1からp3までの全てのデストラクタが呼ばれる.)
  //p1->ptr_ = p3; // p1->ptr_にp3をセット.
  //p2->ptr_ = p3; // p2->prt_にp3をセット.

  // p1の子ポインタをp2, p2の子ポインタをp1にする.(この場合は, 循環参照になるので, デストラクタが呼ばれない.)
  p1->ptr_ = p2; // p1->ptr_にp2をセット.
  p2->ptr_ = p1; // p2->ptr_にp1をセット.

  // プログラムの終了.
  return 0; // 0を返して正常終了.

}

循環参照するようにすると、

$ vi main.cpp 
$ g++ -o main main.cpp test.cpp -std=c++11
$ ./main 
class_test::class_test(10)
class_test::class_test(20)
$

デストラクタが呼ばれない。

そこで、test.hで、

weak_ptrだと、

$ vi main.cpp 
$ g++ -o main main.cpp test.cpp -std=c++11
$ ./main 
class_test::class_test(10)
class_test::class_test(20)
x_ = 20
x_ = 10
class_test::~class_test()
class_test::~class_test()
$

ちゃんとデストラクタが呼ばれる。
このように、shared_ptrのリソース共有だと、循環参照に対応できないので、weak_ptrが必要となる。

Sample/cpp/weak_ptr/weak_ptr/src/weak_ptr at master · bg1bgst333/Sample · GitHub