std::enable_shared_from_this
在标头 <memory> 定义 | ||
template<class T > class enable_shared_from_this; | (C++11 起) | |
std::enable_shared_from_this
能让它的一个已被 std::shared_ptr 类型对象 pt 管理的对象 t 安全地生成其他额外的 std::shared_ptr 实例 pt1、pt2 等等,它们都与 pt 共享对象 t 的所有权。
如果类 T
公开继承了 std::enable_shared_from_this<T>
,那么就会为该类 T
提供成员函数 shared_from_this
。 当 T
类型对象 t 被 std::shared_ptr<T> 类对象 pt 管理时,调用 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 的引用 (受保护成员函数) | |
返回共享 *this 所有权的 std::shared_ptr (公开成员函数) | |
(C++17) | 返回共享 *this 所有权的 std::weak_ptr (公开成员函数) |
[编辑]注解
std::shared_ptr 的构造函数会检测无歧义且可访问的 enable_shared_from_this
基类(即强制公开继承),并且在 weak_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 异常(通过 std::shared_ptr 的构造函数,来源为默认构造的 weak_this
)。
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:// 只有自己可以使用构造函数 Best(Private){} // 其他地方都必须使用此工厂函数// 因此所有 Best 对象均将被 shared_ptr 容纳staticstd::shared_ptr<Best> create(){returnstd::make_shared<Best>(Private());} std::shared_ptr<Best> getptr(){return shared_from_this();}}; struct Bad {std::shared_ptr<Bad> getptr(){returnstd::shared_ptr<Bad>(this);} ~Bad(){std::cout<<"调用 Bad::~Bad()\n";}}; void testGood(){// 好:两个 shared_ptr 共享同一对象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(){// 坏:调用 shared_from_this 但没有 std::shared_ptr 占有调用者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';}} void testBest(){// 最好:同上但无法栈分配它: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; // <- 不会通过编译,因为 Best::Best() 为私有。} void testBad(){// 不好,每个 shared_ptr 都认为它是对象的唯一所有者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';}// 未定义行为:Bad 的二次删除 int main(){ testGood(); misuseGood(); testBest(); testBad();}
可能的输出:
good1.use_count() = 2 bad_weak_ptr best1.use_count() = 2 bad1.use_count() = 1 调用 Bad::~Bad() 调用 Bad::~Bad() *** 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) | 拥有共享对象所有权语义的智能指针 (类模板) |
创建管理一个新对象的共享指针 (函数模板) |