方法
// std::shared_ptr
# include <memory>
// boost::shared_ptr
# include <boost/shared_ptr.hpp>
auto main() -> int
{
boost::shared_ptr< int > b = boost::shared_ptr<int>( new int( 123 ) );
std::shared_ptr< int > s = std::shared_ptr<int>( x.get(), [x] ( ... ) mutable { } );
}
検証
挙動の確認
「方法」の比較的簡潔なコードに、挙動の確認に適当なブロックスコープと std::cout などを仕込む例を紹介。
# include <iostream>
# include <memory>
# include <boost/shared_ptr.hpp>
using namespace std;
int main()
{
std::cout << "scope-A{\n";
{
std::cout << "scope-B{\n";
std::shared_ptr< int > s;
std::cout << "s = " << s << '\n';
{
std::cout << "scope-C{\n";
boost::shared_ptr< int > b = boost::shared_ptr< int >( new int( 123 ) );
std::cout << "b = " << b << '\n';
// 今回は解説の都合 b でキャプチャーすると紛らわしいので bc としてコピーキャプチャーする例示にします。
s = std::shared_ptr<int>( b.get(), [ bc = b ] ( ... ) mutable { std::cout << "reset bc in dtor lambda of s\n"; } );
std::cout << "s = " << s << '\n';
std::cout << "}scope-C\n";
}
std::cout << "s = " << s << '\n';
std::cout << "}scope-B\n";
}
std::cout << "}scope-A\n";
}
↑これをビルドして実行すると、↓こうなる。
scope-A{
scope-B{
s = 0
scope-C{
b = 0x1c595b0
s = 0x1c595b0
}scope-C
s = 0x1c595b0
}scope-B
reset bc in dtor lambda of s
}scope-A
-
scope-A{:main関数の関数スコープの始まり。 -
scope-B{:std::shared_ptr< int > sが宣言されるブロックスコープの始まり。 -
scope-C{:boost::shared_ptr< int > bが宣言、定義され、scope-Bのsに対して「変換」が行われるブロックスコープの始まり。 -
}scope-C: オブジェクトbがスコープを外れ破棄されるタイミング。但し、「変換」が成功していればbはsのカスタムデリーターのラムダ式にbcとしてコピーキャプチャーされているため、bが破棄されてもbcはsのスコープで生存する「はず」というタイミング。 -
}scope-B: 「変換」が成功していればsはscope-Bのbと同じオブジェクトをこの時点までは間接参照できる「はず」の最後のタイミング。ここを超えるとオブジェクトsもスコープにより破棄されるので、sのカスタムデリーターに仕込んだbcの破棄出力が得られる「はず」のタイミング。 -
}scope-A: ↑の(5)とこの(6)の間にsのカスタムデリーターによるbcの破棄出力が得られている「はず」のタイミング。
と、いうわけで、外部から観測する挙動としては意図通りに「変換」できている事がわかる。