std::enable_shared_from_this
| ヘッダ <memory> で定義
|
||
template< class T > class enable_shared_from_this; |
(C++11以上) | |
std::enable_shared_from_this は、現在 std::shared_ptr のインスタンス pt によって管理されているオブジェクト t が、 t の所有権を pt と共有する追加の std::shared_ptr のインスタンス pt1, pt2, ... を、安全に生成できるようにします。
std::enable_shared_from_this<T> からパブリック継承すると、型 T にメンバ関数 shared_from_this が提供されます。 型 T のオブジェクト t が pt という名前の std::shared_ptr<T> で管理されている場合、 T::shared_from_this は t の所有権を pt と共有する新しい std::shared_ptr<T> を返します。
メンバ関数
enable_shared_from_this オブジェクトを構築します (プロテクテッドメンバ関数) | |
enable_shared_from_this オブジェクトを破棄します (プロテクテッドメンバ関数) | |
this への参照を返します (プロテクテッドメンバ関数) | |
*this の所有権を共有する shared_ptr を返します (パブリックメンバ関数) | |
(C++17) |
*this の所有権を共有する weak_ptr を返します (パブリックメンバ関数) |
メンバオブジェクト
| メンバ名 | 定義 |
weak_this (プライベート)(C++17)
|
*this の所有権を最初に共有した制御ブロックを追跡する std::weak_ptr オブジェクト(説明専用) |
ノート
enable_shared_from_this の一般的な実装は、 this を指す弱参照 (std::weak_ptr など) を保持します。 std::shared_ptr のコンストラクタは曖昧でなくアクセス可能な (すなわちパブリック継承でなければなりません) (C++17以上) enable_shared_from_this 基底クラスの存在を検出し、生存している std::shared_ptr によってすでに所有されていなければ、 (C++17以上)内部的に保持している弱参照に新しく作成された std::shared_ptr を代入します。 すでに他の std::shared_ptr によって管理されているオブジェクトに対する std::shared_ptr の構築は、内部的に保持されている弱参照と協調しないため、未定義動作に繋がります。
shared_from_this は、すでに共有されている、つまり、すでに std::shared_ptr<T> によって管理されているオブジェクトに対してのみ、呼ぶことができます。 そうでなければ、動作は未定義です。 (C++17未満)(デフォルト構築された weak_this から shared_ptr のコンストラクタによって) std::bad_weak_ptr が投げられます。 (C++17以上)
enable_shared_from_this は、 お互い関知しない複数の所有者によって2度以上 this が破棄される結果となりがちな std::shared_ptr<T>(this) のような式の、安全な代替を提供します (以下の例を参照してください)。
例
#include <memory>
#include <iostream>
struct Good: std::enable_shared_from_this<Good> // 注: パブリック継承
{
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
struct Bad
{
std::shared_ptr<Bad> getptr() {
return std::shared_ptr<Bad>(this);
}
~Bad() { std::cout << "Bad::~Bad() called\n"; }
};
int main()
{
// 良い例。 2つの shared_ptr は同じオブジェクトを共有します。
std::shared_ptr<Good> gp1 = std::make_shared<Good>();
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
// 悪い例。 shared_ptr がない状態で shared_from_this が呼ばれています。
try {
Good not_so_good;
std::shared_ptr<Good> gp1 = not_so_good.getptr();
} catch(std::bad_weak_ptr& e) {
// 未定義動作 (C++17未満) または std::bad_weak_ptr が投げられます (C++17以上)。
std::cout << e.what() << '\n';
}
// 悪い例。 2つの shared_ptr はそれぞれ自分がそのオブジェクトの唯一の所有者であると思っています。
std::shared_ptr<Bad> bp1 = std::make_shared<Bad>();
std::shared_ptr<Bad> bp2 = bp1->getptr();
std::cout << "bp2.use_count() = " << bp2.use_count() << '\n';
} // 未定義動作 (Bad の二重解放)。
出力例:
gp2.use_count() = 2
bad_weak_ptr
bp2.use_count() = 1
Bad::~Bad() called
Bad::~Bad() called
*** glibc detected *** ./test: double free or corruption
関連項目
(C++11) |
共有オブジェクト所有権のセマンティクスを持つスマートポインタ (クラステンプレート) |