std::enable_shared_from_this
定義於標頭檔案 <memory> |
||
template< class T > class enable_shared_from_this; |
(C++11 起) | |
std::enable_shared_from_this
允許物件 t(當前由名為 pt 的 std::shared_ptr 管理)安全地生成額外的 std::shared_ptr 例項 pt1、pt2 等,這些例項都與 pt 共享 t 的所有權。
公開繼承 std::enable_shared_from_this<T>
為型別 T
提供了一個成員函式 shared_from_this
。如果型別 T
的物件 t 由名為 pt 的 std::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 的所有權 (公開成員函式) | |
(C++17) |
返回一個 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_this
的 std::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 如何更新不明確 | 已明確 |
[編輯] 另請參閱
(C++11) |
具有共享物件所有權語義的智慧指標 (類模板) |
(C++20 起) |
建立一個管理新物件的共享指標 (函式模板) |