Skip to content

Latest commit

 

History

History
104 lines (75 loc) · 4.31 KB

enable_shared_from_this.md

File metadata and controls

104 lines (75 loc) · 4.31 KB

enable_shared_from_this

  • memory[meta header]
  • std[meta namespace]
  • class template[meta id-type]
  • cpp11[meta cpp]
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クラスの正しい使い方は、

  1. shared_ptrで管理するクラスが
  2. このクラスをpublic継承して、
  3. 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);
}
  • std::enable_shared_from_this[color ff0000]

出力

バージョン

言語

  • C++11

処理系

  • Clang: 3.0 [mark verified]
  • GCC: 4.3.6 [mark verified]
  • ICC: ??
  • Visual C++: 2008 (TR1) [mark verified], 2010 [mark verified], 2012 [mark verified], 2013 [mark verified]

参照