名前空間
変種
操作

std::enable_shared_from_this

提供: cppreference.com
< cpp‎ | memory
 
 
 
動的メモリ管理
未初期化記憶域
(C++17)
ガベージコレクションサポート
その他
(C++20)
(C++11)
(C++11)
C のライブラリ
低水準のメモリ管理
 
 
ヘッダ <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> からの public な継承は、メンバ関数 shared_from_this を持つ型 T を提供します。 型 T のオブジェクト tpt という名前の std::shared_ptr<T> で管理されている場合、 T::shared_from_thist の所有権を pt と共有する新しい std::shared_ptr<T> を返します。

目次

[編集] メンバ関数

enable_shared_from_this オブジェクトを構築します
(プロテクテッドメンバ関数)
enable_shared_from_this オブジェクトを破棄します
(プロテクテッドメンバ関数)
this への参照を返します
(プロテクテッドメンバ関数)
*this の所有権を共有する shared_ptr を返します
(パブリックメンバ関数)
*this の所有権を共有する weak_ptr を返します
(パブリックメンバ関数)

[編集] メンバオブジェクト

メンバ名 定義
weak_this (private)(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> // note: public inheritance
{
    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()
{
    // Good: the two shared_ptr's share the same object
    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';
 
    // Bad: shared_from_this is called without having std::shared_ptr owning the caller 
    try {
        Good not_so_good;
        std::shared_ptr<Good> gp1 = not_so_good.getptr();
    } catch(std::bad_weak_ptr& e) {
        // undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)
        std::cout << e.what() << '\n';    
    }
 
    // Bad, each shared_ptr thinks it's the only owner of the object
    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';
} // UB: double-delete of 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

[編集] 関連項目

共有オブジェクト所有権のセマンティクスを持つスマートポインタ
(クラステンプレート) [edit]