命名空间
变体
操作

std::enable_shared_from_this

来自 cppreference.com
< cpp‎ | memory
 
 
工具库
语言支持
类型支持 (基本类型, RTTI)
库特性测试宏 (C++20)
动态内存管理
程序工具
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三方比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
通用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
基本字符串转换
(C++17)
(C++17)

 
动态内存管理
未初始化内存算法
受限未初始化内存算法
分配器
垃圾回收支持
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)



 
 
定义在头文件 <memory>
template< class T > class enable_shared_from_this;
(自 C++11 起)

std::enable_shared_from_this 允许一个当前由名为 ptstd::shared_ptr 管理的对象 t 安全地生成额外的 std::shared_ptr 实例 pt1, pt2, ...,这些实例都与 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 的所有权。

内容

[编辑] 成员函数

构造一个 enable_shared_from_this 对象
(受保护的成员函数)
销毁一个 enable_shared_from_this 对象
(受保护的成员函数)
返回对 *this 的引用
(受保护的成员函数)
返回一个 std::shared_ptr,该对象共享 *this 的所有权
(公共成员函数)
返回一个 std::weak_ptr,该对象共享 *this 的所有权
(公共成员函数)

[编辑] 成员对象

成员名称 定义
weak-this (private) std::weak_ptr 对象跟踪 *this 的第一个共享所有者的控制块。
(仅供说明*)

[编辑] 注释

enable_shared_from_this 的一种常见实现是持有对 *this 的弱引用(例如 std::weak_ptr)。为了说明,弱引用被称为 weak-this,并且被认为是可变的 std::weak_ptr 成员。

当构造 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 创建的 shared_ptr 构造函数抛出)。

enable_shared_from_this 提供了类似 std::shared_ptr<T>(this) 表达式的安全替代方案,该表达式可能会导致多个彼此不知情的拥有者多次销毁 this(请参阅下面的示例)。

[edit] 示例

#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 can't 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's 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

[edit] 缺陷报告

以下行为改变的缺陷报告被追溯应用于之前发布的 C++ 标准。

DR 应用于 发布的行为 正确行为
LWG 2529 C++11 enable_shared_from_this 的规范不明确,可能无法实现 已澄清并修复

[edit] 另请参阅

具有共享对象所有权语义的智能指针
(类模板) [edit]
创建一个管理新对象的共享指针
(函数模板) [edit]