yohhoyの日記

技術的メモをしていきたい日記

shared_ptr相互乗り入れ

C++11標準ライブラリとBoost.Smart_Pointersライブラリでそれぞれ提供される共有ポインタshared_ptrクラステンプレートの相互運用に関するメモ。本記事の内容はStack Overflowで見つけた質問と回答内容に基づく。

注意:あくまで “技術的に相互運用が可能であること” を示すだけで、実行時効率や保守性の観点からは片方で統一するのが望ましい。

#include <memory>
#include <boost/shared_ptr.hpp>

// boost::shared_ptr → std::shared_ptr
template<typename T>
boost::shared_ptr<T> make_shared_ptr(const std::shared_ptr<T>& ptr)
{
  return boost::shared_ptr<T>(ptr.get(), [ptr](T*){});
}

// std::shared_ptr → boost::shared_ptr
template<typename T>
std::shared_ptr<T> make_shared_ptr(const boost::shared_ptr<T>& ptr)
{
  return std::shared_ptr<T>(ptr.get(), [ptr](T*){});
}

変換先shared_ptrオブジェクトのコンストラクタに「元shared_ptrオブジェクトが指す生ポインタ値」と「元shared_ptrオブジェクトのコピーを保持し、自shared_ptrでの所有権放棄時には何もしないカスタムデリータ」を指定している。

shared_ptrが所有権を保持している間は、そのカスタムデリータ(=ラムダ式によるクロージャオブジェクト)によって元shared_ptrの所有権を維持する。自shared_ptrが所有権を放棄するタイミングで、カスタムデリータオブジェクトの解放=元shared_ptrの参照カウントが減らされる。

// 波括弧{}は該当行実行後の所有カウントを表す
std::shared_ptr<int> sp0 = std::make_shared<int>(42);  // std{1}
std::shared_ptr<int> sp1 = sp0;                        // std{2}

boost::shared_ptr<int> bp0 = make_shared_ptr(sp1); // boost{1},std{3}

sp0.reset();  sp1.reset();  // boost{1},std{1}
bp0.reset();                // boost{0},std{0}