命名空间
变体
操作

std::enable_shared_from_this

来自 cppreference.cn
< cpp‎ | memory
 
 
内存管理库
(仅为解释目的*)
未初始化内存算法
(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 前已弃用*)
(在 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 赋值给 weak_this,如果它尚未被活动的 std::shared_ptr 拥有。为已由另一个 std::shared_ptr 管理的对象构造 std::shared_ptr 将不会查询 weak_this,因此将导致未定义的行为。

仅允许在先前共享的对象上调用 shared_from_this,即由 std::shared_ptr<T> 管理的对象。否则,将抛出 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++ 标准。

DR 应用于 已发布行为 正确行为
LWG 2179
(P0033R1)
C++11 给定从 enable_shared_from_this 派生的类型 T,以下行为:
从同一个 T* 对象构造两个 std::shared_ptr<T> 的行为不明确
在这种情况下,行为是
未定义的
LWG 2529
(P0033R1)
C++11 不清楚底层的 std::weak_ptr 如何更新 已明确

[编辑] 参见

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