总结一下shared_from_this的使用注意事项

文章讲述了C++中enable_shared_from_this的作用,如何正确使用shared_from_this获取自身引用,以及在从第三方类继承时可能遇到的问题,特别强调了构造函数中不可调用shared_from_this和使用parent指针创建shared_ptr可能导致的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 类必须从std::enable_shared_from_this继承,并且T必须是类本身。
  • 在类的成员函数中,可以通过调用shared_from_this()来获取一个指向自己的shared_ptr。
  • 在使用shared_from_this()之前,必须确保存在至少一个shared_ptr对象来管理该类的生命周期,否则会抛出std::bad_weak_ptr异常。
  • 不要在类的构造函数中调用shared_from_this(),因为在构造函数中shared_ptr还没有创建。
  • enable_shared_from_this必须要public继承。
  • 使用shared_ptr(pointer)来构建shared_ptr时没有考虑指针指向的实际对象,没有多态性,这可能会引起一些隐秘的错误,下面是一个例子:
#include <iostream>
#include <memory>

using namespace std;
class Base
{
    virtual void baseVTable() {};  //模拟基类是一个多态类型,否则dynamic_cast报错
};
class Derived : virtual public Base, public enable_shared_from_this<Derived>
{
public:
    int a = 10;

    void test()
    {
        cout << shared_from_this()->a << endl;
    }
};
int main() 
{
    auto childSPtr = make_shared<Derived>();
    childSPtr->test();  //输出10

    Base* ptr = new Derived();
    shared_ptr<Base> sPtr = shared_ptr<Base>(ptr);
    shared_ptr<Derived> derivedSPtr = dynamic_pointer_cast<Derived>(sPtr);
    derivedSPtr->test();    //报错
}

在这个例子中,使用指向子类实例的父类指针去创建shared_ptr时,shared_ptr()不知道这个父类指针指向的对象实际上继承了enable_shared_from_this,也就没有做相应的赋值,shared_from_this()会产生报错。
先创建子类的shared_ptr后再转换为父类的shared_ptr就能避免报错。

前四条参考:从第三方定义的类继承时的shared_from_this

<think>好的,我需要回答用户关于C++shared_from_this的用法和代码示例的问题。首先,我得回忆一下这个功能的背景。记得在C++中,当类需要安全地传递自身的shared_ptr时,通常会继承enable_shared_from_this模板类。这样可以使用shared_from_this()方法获得一个指向当前对象的shared_ptr,而不会创建新的控制块,避免多次析构的问题。 用户可能需要了解如何正确继承这个类,以及在什么情况下使用shared_from_this。比如,当类的成员函数需要传递自身的shared_ptr给其他函数或对象时,直接使用this指针构造shared_ptr会导致未定义行为,因为这样会创建多个控制块。这时候必须使用shared_from_this来确保所有的shared_ptr共享同一个控制块。 接下来,我需要准备一个代码示例。例子应该包括一个继承enable_shared_from_this的类,并展示如何正确创建shared_ptr实例,以及调用shared_from_this()。例如,定义一个类MyClass,继承自enable_shared_from_this<MyClass>,然后在成员函数中使用shared_from_this()获取自身的shared_ptr。同时,要强调必须通过shared_ptr来管理对象实例,否则调用shared_from_this()会抛出异常。 然后,用户可能会遇到常见错误,比如直接构造对象而不是使用make_shared,或者在对象未被shared_ptr管理时调用shared_from_this。这部分需要详细说明,避免用户踩坑。此外,可以讨论shared_from_this的内部实现机制,比如它依赖于存储的weak_ptr,以及在构造函数中初始化的过程。 还需要考虑线程安全性,虽然shared_ptr本身有线程安全的引用计数,但在多线程中使用shared_from_this时需要注意对象生命周期的管理。另外,可能的应用场景,比如在异步操作或回调中传递自身的shared_ptr,确保对象在操作完成前保持存活。 最后,总结使用时的关键点:必须公有继承enable_shared_from_this,对象必须由shared_ptr管理,以及不能构造函数或析构函数中调用shared_from_this()。同时,提供相关问题,帮助用户进一步理解相关概念,比如enable_shared_from_this的机制、与weak_ptr的区别,以及线程安全的问题。</think>### C++ `shared_from_this` 用法与示例 `std::enable_shared_from_this` 是 C++ 标准库中的一个模板类,用于在类的成员函数中安全地获取指向当前对象的 `std::shared_ptr`。以下是详细说明和代码示例。 --- #### 核心作用 - 当类需要将自身的 `std::shared_ptr` 传递给其他函数或对象时,直接使用 `this` 指针构造 `std::shared_ptr` 会导致多个独立的引用计数控制块,可能引发未定义行为(如多次析构)。 - 通过继承 `std::enable_shared_from_this`,可以调用 `shared_from_this()` 方法获取已存在的 `std::shared_ptr`,确保所有指针共享同一个控制块。 --- #### 代码示例 ```cpp #include <memory> #include <iostream> class MyClass : public std::enable_shared_from_this<MyClass> { public: void doSomething() { // 获取当前对象的 shared_ptr std::shared_ptr<MyClass> self = shared_from_this(); std::cout << "Use count: " << self.use_count() << std::endl; } }; int main() { // 必须通过 shared_ptr 管理对象 auto obj = std::make_shared<MyClass>(); obj->doSomething(); // 输出:Use count: 1 return 0; } ``` --- #### 关键注意事项 1. **公有继承** 必须公有继承 `std::enable_shared_from_this<T>`,否则 `shared_from_this()` 不可访问。 2. **对象必须由 `shared_ptr` 管理** 若直接构造对象(如 `MyClass obj;`),调用 `shared_from_this()` 会抛出 `std::bad_weak_ptr` 异常[^1]。 3. **禁止在构造函数/析构函数中使用** 此时对象的 `shared_ptr` 控制块尚未完全初始化或已销毁,调用 `shared_from_this()` 会导致未定义行为。 --- #### 常见错误场景 ```cpp // 错误示例:直接构造对象 MyClass obj; obj.doSomething(); // 抛出 std::bad_weak_ptr // 错误示例:手动 new 但未用 shared_ptr 管理 MyClass* rawPtr = new MyClass; rawPtr->doSomething(); // 同样抛出异常 ``` --- #### 内部机制 - `enable_shared_from_this` 内部存储了一个 `std::weak_ptr`,在通过 `std::shared_ptr` 构造对象时,该 `weak_ptr` 会绑定到 `shared_ptr` 的控制块。 - `shared_from_this()` 通过 `weak_ptr::lock()` 生成一个 `std::shared_ptr`,确保引用计数正确。 --- #### 相关问题 1. **为什么 `enable_shared_from_this` 需要模板参数?** 模板参数用于静态类型检查,确保返回的 `shared_ptr` 类型与当前类匹配。 2. **如何避免 `shared_from_this` 的循环引用?** 结合 `std::weak_ptr` 打破循环,例如在观察者模式中存储 `weak_ptr` 而非 `shared_ptr`[^2]。 3. **`shared_from_this` 的线程安全性如何?** `shared_from_this()` 本身是线程安全的,但需确保对象生命周期在多线程中有效。 --- [^1]: 引用示例中的 `sharedFunction()` 需依赖正确初始化的共享资源。 : 引用示例中的 `BUILD_SHARED_LIBS` 选项控制共享库的构建方式,影响内存管理策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值