C++ 中 shared_from_this 的作用与优点详解

1. shared_from_this 的基本概念

shared_from_this 是 C++ 标准库中的一个机制,定义在 <memory> 头文件中,通过 std::enable_shared_from_this 模板类提供。它允许一个对象安全地生成指向自身的 shared_ptr,而不会创建额外的控制块。

基本用法

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    std::shared_ptr<MyClass> getShared() {
        return shared_from_this();
    }
};

int main() {
    auto ptr = std::make_shared<MyClass>();
    auto ptr2 = ptr->getShared();  // 正确共享所有权
}

2. 核心作用

2.1 解决什么问题

在没有 shared_from_this 时,如果对象需要获取自身的 shared_ptr,常见错误做法:

class BadExample {
public:
    std::shared_ptr<BadExample> getShared() {
        return std::shared_ptr<BadExample>(this);  // 危险!创建新控制块
    }
};

auto p1 = std::make_shared<BadExample>();
auto p2 = p1->getShared();
// 当 p1 和 p2 析构时会导致双重释放

shared_from_this 解决了以下关键问题:

  1. 避免多控制块:确保所有 shared_ptr 共享同一个控制块
  2. 防止双重释放:消除因多个控制块导致的重复析构
  3. 安全自引用:使对象能安全地参与回调等需要延长生命周期的场景

2.2 典型应用场景

  1. 异步回调

    class Session : public std::enable_shared_from_this<Session> {
        void asyncWrite() {
            // 捕获 shared_ptr 延长生命周期
            async_write(socket_, buffer_, 
                [self = shared_from_this()](error_code ec, size_t bytes) {
                    self->handleWrite(ec, bytes);
                });
        }
    };
    
  2. 链式调用

    class Builder : public std::enable_shared_from_this<Builder> {
    public:
        Builder& step1() { /*...*/ return *this; }
        Builder& step2() { /*...*/ return *this; }
        
        std::shared_ptr<Builder> build() {
            return shared_from_this();
        }
    };
    
  3. 观察者模式

    class Observable : public std::enable_shared_from_this<Observable> {
        void notify() {
            for (auto& observer : observers_) {
                observer->update(shared_from_this());
            }
        }
    };
    

3. 实现原理

3.1 控制块共享机制

enable_shared_from_this 的核心是一个 weak_ptr 成员:

template<class T>
class enable_shared_from_this {
protected:
    mutable weak_ptr<T> weak_this;
public:
    shared_ptr<T> shared_from_this() {
        return shared_ptr<T>(weak_this);  // 从 weak_ptr 创建 shared_ptr
    }
};

3.2 构造过程

当通过 shared_ptr 构造函数或 make_shared 创建对象时:

  1. 检查类是否继承自 enable_shared_from_this
  2. 如果是,初始化内部的 weak_this 成员,指向新创建的 shared_ptr 的控制块
// 伪代码:shared_ptr 构造函数中的处理
template<typename T>
shared_ptr<T>::shared_ptr(T* ptr) {
    // ...正常控制块初始化...
    
    if constexpr (is_base_of_v<enable_shared_from_this<T>, T>) {
        ptr->weak_this = *this;  // 初始化 weak_ptr
    }
}

3.3 工作流程

User shared_ptr enable_shared_from_this Object make_shared<MyClass>() 分配内存+构造 初始化 weak_this 调用 shared_from_this() 检查 weak_this 创建新 shared_ptr 返回共享所有权的指针 User shared_ptr enable_shared_from_this Object

4. 关键优点

4.1 安全性优势

安全特性说明
避免双重释放保证所有 shared_ptr 共享同一控制块
防止悬空指针weak_this 确保能检测对象是否存活
异常安全操作是原子的,不会中途失败导致状态不一致

4.2 性能优势

性能方面说明
无额外分配复用现有控制块,不新增内存分配
缓存友好使用已存在的控制块,减少缓存未命中
原子操作优化标准库实现通常优化了引用计数操作

4.3 设计优势

设计层面好处
明确所有权显式表达对象参与共享所有权
简化接口不需要传递 shared_ptr 参数
支持链式调用方便实现流畅接口

5. 使用注意事项

5.1 必须通过 shared_ptr 管理

错误用法:

class MyClass : public enable_shared_from_this<MyClass> {};

MyClass obj;  // 错误!栈对象不能使用 shared_from_this
auto p = obj.shared_from_this();  // 未定义行为

正确做法:

auto ptr = std::make_shared<MyClass>();  // 必须通过 shared_ptr 管理
auto p = ptr->shared_from_this();         // 安全

5.2 构造函数中不能调用

class MyClass : public enable_shared_from_this<MyClass> {
public:
    MyClass() {
        // shared_from_this();  // 错误!weak_this 尚未初始化
    }
};

5.3 多继承时的注意事项

需要正确指定模板参数:

class Base : public std::enable_shared_from_this<Base> {};
class Derived : public Base {};

auto d = std::make_shared<Derived>();
auto b = d->shared_from_this();  // 返回 shared_ptr<Base>

如需获取 shared_ptr<Derived>

class Derived : public std::enable_shared_from_this<Derived>, public Base {
    // ...
};

6. 现代 C++ 的扩展功能

6.1 weak_from_this (C++17)

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    std::weak_ptr<MyClass> getWeak() {
        return weak_from_this();  // 安全获取 weak_ptr
    }
};

6.2 协程支持 (C++20)

在协程中安全传递 this

struct Task : std::enable_shared_from_this<Task> {
    struct promise_type {
        std::shared_ptr<Task> get_return_object() {
            return std::make_shared<Task>();
        }
        // ...其他协程方法...
    };
    
    auto operator co_await() {
        return Awaitable(shared_from_this());
    }
};

7. 替代方案比较

方案优点缺点
shared_from_this安全,高效必须继承,有使用约束
传递 shared_ptr直接控制接口污染,性能开销
weak_ptr 回调安全需要额外 lock() 操作

8. 最佳实践

  1. 继承声明:明确公开继承 enable_shared_from_this

    class Widget : public std::enable_shared_from_this<Widget> {
        // ...
    };
    
  2. 工厂模式:强制使用 shared_ptr 创建

    class MyClass : public std::enable_shared_from_this<MyClass> {
    private:
        MyClass() = default;
    public:
        static std::shared_ptr<MyClass> create() {
            return std::make_shared<MyClass>();
        }
    };
    
  3. 文档标注:明确类需要共享所有权

    /**
     * @note This class must be managed by shared_ptr.
     * Use shared_from_this() to obtain shared pointers.
     */
    class SharedType : public enable_shared_from_this<SharedType> {};
    

9. 总结

shared_from_this 是现代 C++ 共享所有权编程的核心工具之一,它:

  1. 解决核心问题:安全获取对象的 shared_ptr 而不创建新控制块
  2. 提供关键保证:避免双重释放、确保线程安全的引用计数
  3. 优化设计模式:简化回调、异步操作和链式调用等场景的实现
  4. 保持高效性:零额外内存分配,复用现有控制块

正确使用 shared_from_this 需要:

  • 始终通过 shared_ptr 管理对象生命周期
  • 不在构造函数中调用
  • 注意多继承时的模板参数指定

这一机制极大增强了 C++ 面向对象编程的安全性,特别是在需要对象自我引用或延长生命周期的场景中,是编写健壮现代 C++ 代码的重要工具。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北辰alk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值