C++11中enable_shared_from_this的用法解析

本文介绍了C++11中的`enable_shared_from_this`模板类,用于在类的成员函数中安全获取共享智能指针`std::shared_ptr`。内容包括`enable_shared_from_this`的作用、何时使用、如何使用以及注意事项,通过实例和源码分析帮助理解其工作原理。

什么是 enable_shared_from_this?

下面摘自 cpp reference 中概述

C++11 开始支持 enable_shared_from_this,它是一个模板类,定义在头文件 <memory>,其原型为:
template< class T > class enable_shared_from_this;

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 被一个为名为 pt 的 std::shared_ptr 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr 对象,它与 pt 共享 t 的所有权。

为什么要用 enable_shared_from_this

  • 需要在类对象的内部中获得一个指向当前对象的 shared_ptr 对象。
  • 如果在一个程序中,对象内存的生命周期全部由智能指针来管理。在这种情况下,要在一个类的成员函数中,对外部返回 this 指针就成了一个很棘手的问题。

什么时候用?

当一个类被共享智能指针 share_ptr 管理,且在类的成员函数里需要把当前类对象作为参数传给其他函数时,这时就需要传递一个指向自身的 share_ptr

如何安全地将 this 指针返回给调用者?

一般来说,我们不能直接将 this 指针返回。如果函数将 this 指针返回到外部某个变量保存,然后这个对象自身已经析构了,但外部变量并不知道,此时如果外部变量再使用这个指针,就会使得程序崩溃。

标准库中的源码

  template<typename _Tp>
    class enable_shared_from_this
    {
   
   
    protected:
      // 构造函数
      constexpr enable_shared_from_this() noexcept {
   
    }
	  
	  // 拷贝构造函数
      enable_shared_from_this(const enable_shared_from_this&) noexcept {
   
    }
      
      // 赋值操作
      enable_shared_from_this&
      operator=(const enable_shared_from_this&) noexcept
      {
   
    return *this; }
      
      // 析构函数
      ~enable_shared_from_this() {
   
    }

    public:
      // 成员函数,返回类型为共享智能指针 shared_ptr
      shared_ptr<_Tp>
      shared_from_this()
      {
   
    return shared_ptr
<think>好的,用户现在想了解关于继承std::enable_shared_from_this的Session类的实现和使用问题。首先,我需要回忆一下enable_shared_from_this的作用。这个模板类主要用于在类的内部获取指向自身的shared_ptr,避免多次创建shared_ptr导致引用计数混乱,从而引发对象被多次删除的问题。 用户之前的问题是关于事件驱动编程的,但这次转向了C++中的智能指针和类的设计。可能需要先确认用户的使用场景,比如是否在异步编程或网络编程中使用Session类,这些场景常见于需要共享资源的情况。 接下来,用户提供的引用中提到了std::iterator_traits和BlueprintNativeEvent,但这些似乎与当前问题关联不大。可能用户之前的问题中有关于C++迭代器或Unreal Engine的内容,但现在的问题焦点在enable_shared_from_this,需要集中解答这个部分。 我需要解释enable_shared_from_this的基本用法,为什么需要继承它,以及如何正确使用shared_from_this()方法。需要注意,使用shared_from_this()的前提是该对象必须已经被托管在shared_ptr中,否则会抛出异常。常见的错误是在构造函数中调用shared_from_this(),这时候对象还未被shared_ptr接管,会导致未定义行为。 然后,需要给出一个具体的Session类示例,展示继承enable_shared_from_this的正确方式。示例代码应该包括构造函数的正确实现,创建shared_ptr的方法,以及如何在成员函数中安全地获取自身的shared_ptr。 另外,需要提到常见的陷阱,比如循环引用问题,虽然enable_shared_from_this本身不会导致循环引用,但在实际使用中如果Session类内部持有其他shared_ptr,可能会引发这种情况,需要用户注意使用weak_ptr来打破循环。 用户可能还关心多线程环境下的使用,需要指出enable_shared_from_this本身并不是线程安全的,如果在多线程环境下使用,需要额外的同步措施。 最后,总结使用场景,比如网络编程中的连接会话管理,异步操作中需要传递自身shared_ptr的情况,以及需要将this指针传递给其他需要shared_ptr的函数或回调时,使用enable_shared_from_this是必要的。 在生成相关问题时,需要考虑用户可能的后续疑问,比如与多线程的结合、性能影响、替代方案等,这些都可以作为相关问题提出,帮助用户进一步探索。</think>#### 使用`std::enable_shared_from_this`的`Session`类实现指南 以下从**核心机制**、**实现步骤**、**典型陷阱**和**应用场景**四个维度解析该问题,提供可直接运行的代码示例。 --- ### 1. **核心机制与必要性** `std::enable_shared_from_this<T>` 是一个模板基类,用于在对象**已被托管到`shared_ptr`的前提下**,安全地获取当前对象的`shared_ptr`或`weak_ptr`。其核心作用包括: - 避免对同一原始指针多次构造`shared_ptr`(导致多次释放)[^1]。 - 在需要将`this`传递给其他函数时,确保引用计数正确管理。 - 支持异步操作中对象生命周期的自动延长(例如网络会话保持活跃状态)[^3]。 --- ### 2. **标准实现步骤与代码** #### 步骤1:继承并声明 ```cpp #include <memory> class Session : public std::enable_shared_from_this<Session> { public: // 必须通过shared_ptr构造(禁用直接实例化) static std::shared_ptr<Session> Create() { return std::shared_ptr<Session>(new Session()); } void Start() { // 正确获取当前对象的shared_ptr auto self = shared_from_this(); // 将self传递给异步操作或其他需要shared_ptr的接口 } private: Session() {} // 强制使用工厂方法创建 }; ``` #### 步骤2:使用工厂函数构造对象 ```cpp int main() { // 正确构造方式 auto session = Session::Create(); session->Start(); // 错误!直接构造会触发未定义行为(shared_from_this()崩溃) // Session* bad_session = new Session(); // delete bad_session; } ``` --- ### 3. **关键陷阱与规避方法** #### 陷阱1:未通过`shared_ptr`管理对象 ```cpp Session session; // 直接实例化对象 session.shared_from_this(); // 运行时抛出std::bad_weak_ptr异常 ``` **规避**:始终通过工厂函数或`std::make_shared`创建对象实例。 #### 陷阱2:在构造函数中调用`shared_from_this()` ```cpp class Session : public std::enable_shared_from_this<Session> { public: Session() { auto self = shared_from_this(); // 崩溃:对象尚未被shared_ptr接管 } }; ``` **规避**:将初始化逻辑移至单独的`Init()`方法,在构造后调用。 #### 陷阱3:循环引用导致内存泄漏 ```cpp class Session : public std::enable_shared_from_this<Session> { public: void SetCallback(std::function<void()> cb) { callback_ = cb; } private: std::function<void()> callback_; }; auto session = Session::Create(); session->SetCallback([session] { /* 操作session */ }); // session和lambda相互持有引用 ``` **规避**:使用`weak_ptr`打破循环: ```cpp auto session = Session::Create(); std::weak_ptr<Session> weak_session = session; session->SetCallback([weak_session] { if (auto s = weak_session.lock()) { // 安全使用s } }); ``` --- ### 4. **典型应用场景** 1. **异步网络通信**:在Boost.Asio中传递会话对象到异步回调[^3]。 ```cpp void Session::AsyncRead() { socket_.async_read_some(buffer_, [self = shared_from_this()](auto error, auto size) { self->HandleRead(error, size); }); } ``` 2. **观察者模式**:事件触发时通知多个观察者,无需手动管理观察者的生命周期。 3. **资源池管理**:对象需要主动将自己归还到池中时(如数据库连接池)。 --- ### 5. **扩展:与CRTP模式的结合** 通过**Curiously Recurring Template Pattern**优化类型安全: ```cpp template <typename Derived> class EnableShared : public std::enable_shared_from_this<Derived> { public: std::shared_ptr<Derived> shared_from_this() { return std::enable_shared_from_this<Derived>::shared_from_this(); } }; class Session : public EnableShared<Session> { /* ... */ }; ``` ---
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值