Namespaces
Variants

std:: enable_shared_from_this

From zh.cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
定义于头文件 <memory>
template < class T >
class enable_shared_from_this ;
(C++11 起)

std::enable_shared_from_this 允许当前由名为 pt 的 std::shared_ptr 管理的对象 t 安全地生成其他 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 的引用
(受保护成员函数)
返回共享 * this 所有权的 std::shared_ptr
(公开成员函数)
返回共享 * this 所有权的 std::weak_ptr
(公开成员函数)

备注

在没有歧义且可访问(即公开)的 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::weak_ptr 构造 std::shared_ptr 会抛出异常)。

enable_shared_from_this 提供了表达式 std::shared_ptr<T>(this) 的安全替代方案,后者很可能导致 this 被多个彼此不知晓的所有者多次销毁(参见下面的示例)。

功能特性测试 宏 值 标准 特性
__cpp_lib_constexpr_memory 202506L (C++26) 常量表达式 std::enable_shared_from_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中
    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()
{
    // 良好实践:两个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()
{
    // 错误实践:在没有std::shared_ptr拥有调用者的情况下调用shared_from_this
    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() 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)
具有共享对象所有权语义的智能指针
(类模板)
创建管理新对象的共享指针
(函数模板)