C++ std::enable_shared_from_this<T>的作用

std::enable_shared_from_this<T> 是 C++ 标准库中的一个模板类,用于解决一个特定问题:当一个对象本身已被 std::shared_ptr 管理时,如何在该对象的方法内部安全地获取指向自身的 std::shared_ptr

核心作用

提供安全的 shared_from_this() 方法,返回一个与现有 shared_ptr 共享所有权的智能指针,避免创建额外的控制块。


不使用时的问题:双重控制块(Undefined Behavior)

当对象已被 shared_ptr 管理时,如果在成员函数中直接用 this 创建新 shared_ptr,会生成独立的控制块。这导致:

  1. 多个控制块独立管理同一对象
  2. 引用计数不共享
  3. 对象会被多次释放(双重释放)

错误示例代码

#include <memory>
#include <iostream>

class UnsafeClass {
public:
    void process() {
        // 危险!创建独立控制块的新 shared_ptr
        auto self = std::shared_ptr<UnsafeClass>(this);
        std::cout << "Use count: " << self.use_count() << "\n"; // 输出 1(错误!)
    }
};

int main() {
    auto ptr = std::make_shared<UnsafeClass>();
    ptr->process();  // 此时有两个控制块管理同一对象
    
    // 程序结束时会双重释放,导致崩溃!
}

输出示例

Use count: 1
free(): double free detected in tcache 2  // 崩溃!

使用 enable_shared_from_this 的正确方式

通过继承 enable_shared_from_this<T> 并调用 shared_from_this() 获取安全的共享指针。

正确示例代码

#include <memory>
#include <iostream>

class SafeClass : public std::enable_shared_from_this<SafeClass> {
public:
    void process() {
        // 安全获取共享指针(共享控制块)
        auto self = shared_from_this();
        std::cout << "Use count: " << self.use_count() << "\n"; // 输出 2(正确)
    }
};

int main() {
    auto ptr = std::make_shared<SafeClass>();  // 必须先由 shared_ptr 管理对象
    ptr->process();  // 安全:共享同一控制块
    
    // 程序正常退出
}

输出

Use count: 2

关键规则

  1. 必须公有继承
    class T : public enable_shared_from_this<T>

  2. 对象必须已被 shared_ptr 管理
    调用 shared_from_this() 前需存在管理该对象的 shared_ptr,否则抛出 std::bad_weak_ptr

  3. 禁止在构造/析构中调用
    构造时控制块未就绪,析构时控制块已销毁


典型应用场景

class Server : public std::enable_shared_from_this<Server> {
public:
    void start() {
        // 将自身传递给异步回调(安全共享所有权)
        async_task([self = shared_from_this()] {
            self->handle_request();
        });
    }
    
    void handle_request() { /* ... */ }
};

总结

  • 不用 → 多控制块 → 双重释放 → 未定义行为
  • 正确使用 → 共享控制块 → 安全生命周期管理
    始终通过 shared_from_this() 获取成员函数中的自引用智能指针。

posted on 2026-01-03 10:40  四季萌芽V  阅读(0)  评论(0)    收藏  举报

导航