std::enable_shared_from_this

来自cppreference.com
< cpp‎ | memory
 
 
工具库
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(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 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。

若一个类 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 的引用
(受保护成员函数)
返回共享 *this 所有权的 std::shared_ptr
(公开成员函数)
返回共享 *this 所有权的 std::weak_ptr
(公开成员函数)

成员对象

成员名 定义
weak-this (仅用于阐释) 追踪 *this 的首个共享占有者的控制块的 std::weak_ptr 对象。

注解

enable_shared_from_this 的常见实现为:其内部保存着一个对 *this 的弱引用(例如 std::weak_ptr)。为阐释起见,称该弱引用为 weak-this 并认为它是 mutable 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 异常(通过 shared_ptr 的构造函数,来源为默认构造的 weak-this)。

enable_shared_from_this 提供安全的替用方案,以替代 std::shared_ptr<T>(this) 这样的表达式(这种不安全的表达式可能会导致 this 被多个互不知晓的所有者析构,见下方示例)。

示例

#include <memory>
#include <iostream>
 
struct Good : std::enable_shared_from_this<Good> // 注:公开继承
{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};
 
struct Best : std::enable_shared_from_this<Best> // 注:公开继承
{
    std::shared_ptr<Best> getptr() {
        return shared_from_this();
    }
    // 无公开构造函数,仅工厂函数,故无法令 getptr 返回 nullptr 。
    [[nodiscard]] static std::shared_ptr<Best> create() {
        // 不使用 std::make_shared<Best> ,因为构造函数为私有。
        return std::shared_ptr<Best>(new Best());
    }
private:
    Best() = default;
};
 
 
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()
{
    // 坏:调用 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()
{
    // 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: 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 2529 C++11 enable_shared_from_this 的规范不清晰且可能无法实现 澄清并修复

参阅

拥有共享对象所有权语义的智能指针
(类模板)