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