namespace std {
template <class T>
class enable_shared_from_this;
}
概要
enable_shared_from_thisは、shared_ptrで管理しているオブジェクトのthisポインタを、shared_ptrとして扱うことを可能にするためのクラスである。
thisポインタを単純にshared_ptr<T>(this)としてしまうと、参照カウントが増えず、deleteが2重に呼ばれてしまいバグを引き起こすことになるため、そうならないようにこのクラスを使用してthisを扱う。
このクラスは、shared_ptrとして管理するクラスの基底クラスとして使用する。このクラスをpublic継承したクラスでpublicメンバ関数shared_from_this()を使用することで、thisを指すshared_ptrオブジェクトを取得できる。
このクラスを継承する際には、このクラスのテンプレート引数として、派生クラス(このクラスを継承するクラス自身)を指定すること。(このようにテンプレート引数を指定する方法を、CRTP:Curiously Recurring Template Patternと言う)
正しい使い方と、誤った使い方
enable_shared_from_thisクラスの正しい使い方は、
shared_ptrで管理するクラスが- このクラスをpublic継承して、
shared_from_this()メンバ関数を使用して、thisを指すshared_ptrオブジェクトを取得する。
というものだが、これに反して誤った使い方をしてしまう場合がある。以下は、誤った使い方なので、正しい使い方を確認すること。
shared_ptrで管理していないクラスオブジェクトに、このクラスを使用するのは間違い。
struct X : public std::enable_shared_from_this<X> {
void func() {
auto self = shared_from_this(); // (2) NG : thisがshared_ptrで管理されていない
}
};
auto ptr = new X(/*...*/); // (1) shared_ptr管理でない場合...
ptr->func();
protectedメンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
コンストラクタ | C++11 |
(destructor) |
デストラクタ | C++11 |
operator= |
代入演算子 | C++11 |
publicメンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
shared_from_this |
thisポインタをshared_ptrに変換する |
C++11 |
weak_from_this |
thisポインタをweak_ptrに変換する |
C++17 |
例
#include <cassert>
#include <memory>
struct X : public std::enable_shared_from_this<X> {
std::shared_ptr<X> f()
{
// thisを指すshared_ptrオブジェクトを作る
return shared_from_this();
}
};
int main()
{
std::shared_ptr<X> p(new X());
std::shared_ptr<X> q = p->f();
assert(p == q);
}
出力
バージョン
言語
- C++11
処理系
- Clang: 3.0 ✅
- GCC: 4.3.6 ✅
- ICC: ??
- Visual C++: 2008 (TR1) ✅, 2010 ✅, 2012 ✅, 2013 ✅