std::enable_shared_from_this

来自cppreference.com
< cpp‎ | memory
 
 
内存管理库
(仅用于阐述*)
分配器
未初始化内存算法
受约束的未初始化内存算法
内存资源
未初始化存储 (C++20 前)
(C++17 弃用)
(C++17 弃用)

垃圾收集器支持 (C++23 前)
(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 能让它的一个已被 std::shared_ptr 类型对象 pt 管理的对象 t 安全地生成其他额外的 std::shared_ptr 实例 pt1pt2 等等,它们都与 pt 共享对象 t 的所有权。

如果类 T 公开继承了 std::enable_shared_from_this<T>,那么就会为该类 T 提供成员函数 shared_from_this。 当 T 类型对象 tstd::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
(公开成员函数)
返回共享 *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 容纳
    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()\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 使之明确

[编辑] 参阅

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