C++11新特性:enable_shared_from_this

本文详细介绍了std::enable_shared_from_this的功能和使用方法,包括如何通过成员函数shared_from_this()安全地创建多个std::shared_ptr实例来共享同一对象的所有权。同时,通过示例对比了正确和错误的用法,并解释了在异步调用中如何利用此功能实现对象的保活。

template< class T > class enable_shared_from_this;

shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;

  • std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, … ) ,它们与 pt 共享对象 t 的所有权
  • 若一个类 T 继承 std::enable_shared_from_this ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr 对象,它与 pt 共享 t 的所有权
返回值

返回一个std :: shared_ptr ,它与所有引用* this的现有std :: shared_ptr共享* this的所有权

使用方法

允许仅在先前共享的对象上调用shared_from_this,即在由std :: shared_ptr管理的对象上(特别是在构造* this期间不能调用shared_from_this)。

否则行为是未定义的(直到C ++ 17)抛出std :: bad_weak_ptr(由默认构造的weak_this中的shared_ptr构造函数)。

例子
#include <memory>
#include <iostream>
 
struct Good: std::enable_shared_from_this<Good> // note: public inheritance
{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};
 
struct Bad
{
    std::shared_ptr<Bad> getptr() {
    	//这样会造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。
        return std::shared_ptr<Bad>(this); 
    }
    ~Bad() { std::cout << "Bad::~Bad() called\n"; }
};
 
int main()
{
    // Good: the two shared_ptr's share the same object
    std::shared_ptr<Good> gp1 = std::make_shared<Good>();
    std::shared_ptr<Good> gp2 = gp1->getptr();
    std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
 
    // 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';    
    }
 
    // Bad, each shared_ptr thinks it's the only owner of the object
    std::shared_ptr<Bad> bp1 = std::make_shared<Bad>();
    std::shared_ptr<Bad> bp2 = bp1->getptr();
    std::cout << "bp2.use_count() = " << bp2.use_count() << '\n';
} // UB: double-delete of Bad
输出:
gp2.use_count() = 2
bad_weak_ptr
bp2.use_count() = 1
Bad::~Bad() called
Bad::~Bad() called
*** glibc detected *** ./test: double free or corruption
应用场景

异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。

参考

<https://blog.youkuaiyun.com/caoshangpa/article/details/79392878 >

`std::enable_shared_from_this` 是 C++ 标准库中的一个模板类,用于解决对象在已被 `std::shared_ptr` 管理的情况下,安全地生成新的 `shared_ptr` 指向自身的问题。以下是详细解释: ### 作用 1. **安全共享所有权**:当对象需要通过 `this` 指针生成新的 `shared_ptr` 时(例如在成员函数中返回 `shared_ptr<this>`),直接使用 `std::shared_ptr<T>(this)` 会导致重复管理同一对象,可能引发重复析构。 2. **继承使用**:通过让类继承 `std::enable_shared_from_this<T>`,可以调用其成员函数 `shared_from_this()`,生成一个与现有 `shared_ptr` 共享所有权的指针。 ### 关键点 - **必须由 `shared_ptr` 管理**:对象必须已被 `std::shared_ptr` 管理(即存在至少一个 `shared_ptr` 指向它),否则调用 `shared_from_this()` 会抛出 `std::bad_weak_ptr` 异常。 - **避免重复析构**:确保所有生成的 `shared_ptr` 共享同一个引用计数。 ### 示例代码 ```cpp #include <memory> #include <iostream> class MyClass : public std::enable_shared_from_this<MyClass> { public: std::shared_ptr<MyClass> getShared() { return shared_from_this(); // 安全生成新的 shared_ptr } }; int main() { auto ptr = std::make_shared<MyClass>(); auto ptr2 = ptr->getShared(); // 共享所有权 std::cout << ptr.use_count() << std::endl; // 输出 2 return 0; } ``` ### 注意事项 1. **不要在构造函数中调用**:此时对象尚未被 `shared_ptr` 管理,调用 `shared_from_this()` 会导致未定义行为。 2. **线程安全**:`shared_from_this()` 本身是线程安全的,但需确保对象生命周期由 `shared_ptr` 管理。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值