名稱空間
變體
操作

std::enable_shared_from_this

來自 cppreference.com
< cpp‎ | 記憶體
 
 
記憶體管理庫
(僅作說明*)
未初始化記憶體演算法
(C++17)
(C++17)
(C++17)
受約束的未初始化
記憶體演算法
C 庫

分配器
記憶體資源
垃圾回收支援
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
未初始化儲存
(直到 C++20*)
(直到 C++20*)
顯式生命週期管理
 
 
定義於標頭檔案 <memory>
template< class T >
class enable_shared_from_this;
(C++11 起)

std::enable_shared_from_this 允許物件 t(當前由名為 ptstd::shared_ptr 管理)安全地生成額外的 std::shared_ptr 例項 pt1pt2 等,這些例項都與 pt 共享 t 的所有權。

公開繼承 std::enable_shared_from_this<T> 為型別 T 提供了一個成員函式 shared_from_this。如果型別 T 的物件 t 由名為 ptstd::shared_ptr<T> 管理,則呼叫 T::shared_from_this 將返回一個新的 std::shared_ptr<T>,它與 pt 共享 t 的所有權。

目錄

[編輯] 資料成員

成員 描述
mutable std::weak_ptr<T> weak_this 跟蹤 *this 的第一個共享所有者的控制塊的物件
(僅用於闡釋的成員物件*)

[編輯] 成員函式

構造一個 enable_shared_from_this 物件
(受保護成員函式)
銷燬一個 enable_shared_from_this 物件
(受保護成員函式)
返回對 *this 的引用
(受保護成員函式)
返回一個 std::shared_ptr,它共享 *this 的所有權
(公開成員函式)
返回一個 std::weak_ptr,它共享 *this 的所有權
(公開成員函式)

[編輯] 注意

std::shared_ptr 的建構函式會檢測是否存在明確且可訪問的(即公共繼承是強制性的)enable_shared_from_this 基類,如果尚未被活動的 std::shared_ptr 擁有,則會將新建立的 std::shared_ptr 賦值給 weak_this。為已被另一個 std::shared_ptr 管理的物件構造 std::shared_ptr 將不會查詢 weak_this,因此會導致未定義行為。

只允許對先前共享的物件(即由 std::shared_ptr<T> 管理的物件)呼叫 shared_from_this。否則,將丟擲 std::bad_weak_ptr(由預設構造的 weak_thisstd::shared_ptr 建構函式丟擲)。

enable_shared_from_this 提供了一種安全的替代方案,以替代類似 std::shared_ptr<T>(this) 的表示式,因為後者很可能會導致 this 被多個彼此不知情的擁有者多次銷燬(參見下面的示例)。

[編輯] 示例

#include <iostream>
#include <memory>
 
class Good : public std::enable_shared_from_this<Good>
{
public:
    std::shared_ptr<Good> getptr()
    {
        return shared_from_this();
    }
};
 
class Best : public std::enable_shared_from_this<Best>
{
    struct Private{ explicit Private() = default; };
 
public:
    // Constructor is only usable by this class
    Best(Private) {}
 
    // Everyone else has to use this factory function
    // Hence all Best objects will be contained in shared_ptr
    static std::shared_ptr<Best> create()
    {
        return std::make_shared<Best>(Private());
    }
 
    std::shared_ptr<Best> 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"; }
};
 
void testGood()
{
    // Good: the two shared_ptr's share the same object
    std::shared_ptr<Good> good0 = std::make_shared<Good>();
    std::shared_ptr<Good> good1 = good0->getptr();
    std::cout << "good1.use_count() = " << good1.use_count() << '\n';
}
 
void misuseGood()
{
    // 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';
    }
}
 
void testBest()
{
    // Best: Same but cannot stack-allocate it:
    std::shared_ptr<Best> best0 = Best::create();
    std::shared_ptr<Best> best1 = best0->getptr();
    std::cout << "best1.use_count() = " << best1.use_count() << '\n';
 
    // Best stackBest; // <- Will not compile because Best::Best() is private.
}
 
void testBad()
{
    // Bad, each shared_ptr thinks it is the only owner of the object
    std::shared_ptr<Bad> bad0 = std::make_shared<Bad>();
    std::shared_ptr<Bad> bad1 = bad0->getptr();
    std::cout << "bad1.use_count() = " << bad1.use_count() << '\n';
} // UB: double-delete of Bad
 
int main()
{
    testGood();
    misuseGood();
 
    testBest();
 
    testBad();
}

可能的輸出

good1.use_count() = 2
bad_weak_ptr
best1.use_count() = 2
bad1.use_count() = 1
Bad::~Bad() called
Bad::~Bad() called
*** glibc detected *** ./test: double free or corruption

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 2179
(P0033R1)
C++11 給定從 enable_shared_from_this 派生的型別 T
從同一個 T* 物件構造兩個 std::shared_ptr<T> 的行為不明確
在這種情況下,行為是
未定義的
LWG 2529
(P0033R1)
C++11 底層 std::weak_ptr 如何更新不明確 已明確

[編輯] 另請參閱

具有共享物件所有權語義的智慧指標
(類模板) [編輯]
建立一個管理新物件的共享指標
(函式模板) [編輯]