名前空間
変種
操作

std::enable_shared_from_this

提供: cppreference.com
< cpp‎ | memory
 
 
ユーティリティライブラリ
汎用ユーティリティ
日付と時間
関数オブジェクト
書式化ライブラリ (C++20)
(C++11)
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)
スワップと型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
一般的な語彙の型
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

初等文字列変換
(C++17)
(C++17)
 
動的メモリ管理
スマートポインタ
(C++11)
(C++11)
(C++11)
(C++17未満)
(C++11)
enable_shared_from_this
(C++11)
アロケータ
メモリリソース
未初期化記憶域
ガベージコレクションサポート
その他
(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> からパブリック継承すると、型 T にメンバ関数 shared_from_this が提供されます。 型 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 (プライベート)(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

[編集] 関連項目

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