C++1z shared_from_thisの指す先が書き換わらないことを規定

thisポインタをstd::shared_ptrとして取得するための機能として、std::enable_shared_from_this基本クラスとそのメンバ関数shared_from_this()があります。

std::enable_shared_from_thisから派生したクラスのオブジェクトをnewしてshared_ptrコンストラクタに渡すと、そのオブジェクトのthisshared_ptrとして取得できるようになります。

しかし、以下のように同じポインタから複数shared_ptrオブジェクトを作った場合に、shared_from_this()で返されるshared_ptrがどのオブジェクトを指すのか規定されていませんでした。

#include <memory>

using namespace std;

int main()
{
  struct X : public enable_shared_from_this<X> { };
  auto xraw = new X;
  shared_ptr<X> xp1(xraw);  // #1
  {
    shared_ptr<X> xp2(xraw, [](void*) { });  // #2
  }
  xraw->shared_from_this();  // #3
}

実装によっては、 #3 がxp1を指す場合もあれば、xp2を指す場合もありました。xp2を指す場合は、shared_from_this()の再束縛が行われることを意味します。

C++1zでは、shared_from_this()が再束縛されないことが既定されます(この場合はxp1を指し続けます)。また、thisを束縛する動作がスレッドセーフではないことも明記されます。

元々未規定だった動作ですが、xp2を指すことを期待していたプログラムは動作しなくなる可能性があるので注意してください。

また、再束縛されない仕様を明確にすることを主な目的として、std::enable_shared_from_thisクラスに、weak_ptrthisを返すweak_from_this()メンバ関数が追加されます。

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。