首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么需要一个shared_from_this而不是直接使用这个指针?

std::enable_shared_from_this 是 C++11 引入的一个模板类,它允许对象从其成员函数中获取一个指向自身的 std::shared_ptr。使用 shared_from_this 的主要原因涉及到 std::shared_ptr 的内部引用计数机制和避免潜在的内存管理问题。

基础概念

  • std::shared_ptr: 是一个智能指针,它允许多个 shared_ptr 实例共享同一个对象的所有权。对象的销毁会在最后一个拥有它的 shared_ptr 被销毁或重置时发生。
  • std::enable_shared_from_this: 是一个模板类,它允许对象生成额外的 shared_ptr 实例,这些实例与已经存在的 shared_ptr 实例共享所有权。

为什么需要 shared_from_this?

  1. 避免悬挂指针: 如果直接使用原始指针或非共享的智能指针(如 std::unique_ptr)来创建新的 shared_ptr,可能会导致悬挂指针。例如,如果一个对象已经被一个 shared_ptr 管理,然后你尝试通过原始指针创建一个新的 shared_ptr,这将导致两个独立的引用计数器,当原始的 shared_ptr 被销毁时,对象可能被错误地销毁,而新的 shared_ptr 仍然持有悬挂指针。
  2. 确保共享所有权: shared_from_this 确保新的 shared_ptr 实例与已经存在的 shared_ptr 实例共享同一个控制块,从而保证对象的所有权是共享的。

示例代码

代码语言:txt
复制
#include <iostream>
#include <memory>

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    void doSomething() {
        // 使用 shared_from_this 获取指向自身的 shared_ptr
        std::shared_ptr<MyClass> self = shared_from_this();
        std::cout << "Doing something with shared_ptr count: " << self.use_count() << std::endl;
    }
};

int main() {
    // 创建一个 MyClass 的 shared_ptr 实例
    std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();
    
    // 调用成员函数,内部使用 shared_from_this
    obj->doSomething();
    
    return 0;
}

应用场景

  • 回调和异步操作: 当对象需要在异步操作中保持存活时,可以使用 shared_from_this 来确保对象在回调执行期间不会被销毁。
  • 资源管理: 在需要共享资源管理的复杂系统中,shared_from_this 可以帮助避免资源泄漏和悬挂指针。

解决问题的方法

如果你遇到了与 shared_from_this 相关的问题,通常是因为以下原因:

  1. 未正确继承 std::enable_shared_from_this: 确保你的类继承自 std::enable_shared_from_this
  2. 在构造函数中使用 shared_from_this: 在构造函数中使用 shared_from_this 是不安全的,因为此时对象可能还没有被完全构造,也没有与之关联的 shared_ptr
  3. 使用原始指针创建 shared_ptr: 避免通过原始指针创建新的 shared_ptr,除非你确切知道你在做什么,并且已经采取了适当的预防措施。

通过理解和正确使用 shared_from_this,可以有效地管理对象的生命周期,避免内存泄漏和其他与资源管理相关的问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

为什么我应该使用指针而不是对象本身

我发现使用 C++ 的人经常用指针表示对象,比如像下面这样: Object *myObject = new Object; 而不是, Object myObject; 或者在调用成员函数的时候,都会这样...: myObject->testFunc(); 而不是, myObject.testFunc(); 我有点想不明白为什么这么做?...你需要延长对象生命周期。 意思是说你想一直使用某个地址位置的变量,而不是它的副本,对于后者,我们更应该使用 Object myObject; 的语法。 你需要很多内存。...切片的意思就是说:在函数传参处理多态变量时,如果一个派生类对象在向上转换(upcast),用的是传值的方式,而不是指针和引用,那么,这个派生类对象在 upcast 以后,将会被 slice 成基类对象,...C++ 17 新增了 std::optional,那么这个问题也可以得到解决。 你想通过解耦编译单元来减少编译时间: 如果对象都是指针指向的,那么只需要这个类型的前向声明就可以。

1.4K10

为什么我们能在主线程直接使用 Handler,而不需要创建 Looper ?

每个Handler 的线程都有一个 Looper ,主线程当然也不例外,但是我们不曾准备过主线程的 Looper 而可以直接使用,这是为何?...事实上它并不是一个线程,而是主线程操作的管理者,所以吧,我觉得把 ActivityThread 认为就是主线程无可厚非,另外主线程也可以说成 UI 线程。...} 可以看到在 ActivityThread 里 调用了 Looper.prepareMainLooper() 方法创建了 主线程的 Looper ,并且调用了 loop() 方法,所以我们就可以直接使用...-文完- 后续可能还会更新类似的小型知识点,相对于长篇的文章来讲我不需要花费大量的时间写作,对于读者来讲也没有阅读压力,希望对你有所帮助。

43530
  • muduo网络库学习之EventLoop(五):TcpConnection生存期管理(连接关闭)

    shared_from_this() 的使用: class TcpConnection : boost::noncopyable,     public boost::enable_shared_from_this... shared_from_this()  会用当前对象的裸指针构造一个临时智能指针对象,引用计数加1,但马上会被析构,又减1,故无论调用多少 次,对引用计数都没有影响。...TcpConnectionPtr guardThis(shared_from_this()); 为什么不能直接写成TcpConnectionPtr guardThis(this); ?...因为这样写的话,guardThis的引用计数就为1,而不是2,如下例所示: #include #include<boost/shared_ptr.hpp... s(r);     std::cout << s.use_count() << std::endl; //1     assert(p == s); //断言失败     return 0; } 直接用裸指针生成智能指针对象

    1.4K60

    C++雾中风景14:CRTP, 模板的黑魔法

    管理,且需要通过类的成员函数里需要把当前类对象包装为智能指针传递出一个指向自身的share_ptr时。...这里只是用到了模板派生,让父类能够在编译器感知到子类的模板存在,二者不是真正意义上的继承关系。 这里只分析下面两个问题: 为什么Bad类直接通过this构造shared_ptr会存在问题?...因为虚函数的调用需要通过指针查找虚函数表来进行调用,同时类的对象因为不需要存储虚函数指针,也会带来一部分存储的开销。而通过CRTP,恰恰就能通过静态多态的方式,规避上述问题。...它就是一个典型的CRTP的使用,利用静态多态的方式。将虚函数的调用转换为函数指针的调用,这个在实际聚合函数的实现过程之中能够大大提高计算的效率。...而通过getAddressOfAddFunction就可以通过addFree的强制类型转换,直接获得子类的函数指针.(这个过程在编译期间就可以完成,所以称之为静态多态。)

    1.7K32

    C++11新特性:enable_shared_from_this解决大问题

    实际上,在使用现代C++之前,我们也是这么做的,做代码走查的时候不管别的,先看下有没有使用new或者malloc。如果有就直接向后看。检查有没有delete或者free,是不是成对出现。...enable_shared_from_this从本质上来说解决了不能直接冲this对象构造智能指针的问题,但是使用时也需要注意,既返回的智能智能必须要通过shared_from_this()获取,当然也可以不用...在类中提供了一个获取智能指针的方法。在main函数中使用时,同样,也是先定义一个类的指针,然后初始化了_myCar1,_myCar2则是通过类中提供的获取指针的方法获取了智能指针对象。...因此,在使用上述方法时必须要使用智能指针的构造函数先初始化一个智能指针。...除此之外,在使用std::enable_shared_from_this时要保证类是公有继承的,至于为什么不能私有继承或者受保护的继承,欢迎大家留言评论。

    5.4K40

    掌握C++中智能指针的综合指南:深入现代内存管理

    在多线程中,要防止一个线程在使用智能指针,而另一个线程删除指针指针问题,可以使用weak_ptr的lock()方法。...shared_ptr中提到不能直接将this指针返回shared_ptr,需要通过派生std::enable_shared_from_this类,并通过其方法shared_from_this来返回指针;...原因是std::enable_shared_from_this类中有一个weak_ptr,这个weak_ptr用来观察this智能指针,调用shared_from_this()方法是,会调用内部这个weak_ptr...得到了一个容纳NULL指针的sp_null对象。在使用wp前需要调用wp.expired()函数判断一下。因为wp还仍旧存在,虽然引用计数等于0,仍有某处“全局”性的存储块保存着这个计数信息。...(2)多线程代码操作的不是同一个shared_ptr的对象这里指的是管理的数据是同一份,而shared_ptr不是同一个对象。 比如多线程回调的lambda的是按值捕获的对象。

    25000

    C++智能指针的正确使用方式

    同时也解释了为什么要用shared_from_this以及智能指针的函数传参问题。 对象所有权 首先需要理清楚的概念就是对象所有权的概念。...而w2获得了对象所有权,但因为此时w已不再持有对象,因此w2的引用计数为1。 性能 内存占用高 shared_ptr的内存占用是裸指针的两倍。因为除了要管理一个裸指针外,还要维护一个引用计数。...如果,一个shared_ptr需要将所有权共享给另外一个新的shared_ptr,而我们确定在之后的代码中都不再使用这个shared_ptr,那么这是一个非常鲜明的移动语义。...可以使用BlockingQueue>将对象转移到另外一个线程中释放,从而解放关键线程。 为什么要用shared_from_this?...在函数中保存智能指针 假如我们需要在函数中把这个智能指针保存起来,这个时候建议直接传值。

    10.1K42

    Chapter 4: Smart Pointers

    a 相关的引用计数,来判断它是不是最后一个指向该对象 a 的智能指针,这个引用计数追踪有多少个 std::shared_ptr 在指向对象 a ,每构造一个指向 a 的 std::shared_ptr...因为这些自定义析构器的内存和 std::shared_ptr 内存不是同一片内存 更具体的说, std::shared_ptr 包含的是一个指向对象的指针和一个指向控制块的指针,而这个控制块里面包含引用计数...::auto_ptr )来构造一个 std::shared_ptr 时,需要创建一个控制块 用一个原始指针来构造一个 std::shared_ptr 时,需要创建一个控制块 以上规则暗示了:如果使用一个原始指针分别构造了多个...在这个情况下,调用者从工厂函数中收到智能指针,然后由调用者来决定它的声明周期,而当指向某个 id 最后一个使用的指针销毁时,对象也会被销毁,那么缓存中的指针就会悬空,因此在后续查询的时候需要检测命中的指针是否已经悬空...内部使用括号进行完美转发参数,如果要使用花括号初始器来构造智能指针,必须直接使用 new ,但是完美转发不能直接转发花括号初始化列表,必须先保存为 std::initializer_list 对象,然后在传递给

    1.6K20

    Smart Pointers:八年,内存泄露终于解决

    如果我们仔细设计并限制智能指针的使用,例如没有循环链接,这意味着我们不需要 weak ptr,我们可以为 SRS 实现一个简单且易于维护的智能指针。...• make_shared:不支持这个辅助函数,因为我们不考虑通过 new 操作符的性能问题。 • shared_from_this:不支持这个辅助模板,因为我们不需要这个特性。...否则多个地方都需要实现重复的逻辑, 相反会更复杂。此外,由于Executor引用的是ISrsResource,因此我们使用Resource Ptr指针对象,而不是直接使用Shared Ptr指针。...而WebRTC over TCP 则新增了一个TCP连接,我们使用SrsRtcTcpConn管理这个Tcp连接。...参考 #4083 SrsRtcConnection使用Shared Resource引用SrsRtcTcpConn对象,而SrsRtcTcpConn直接引用SrsRtcConnection的裸指针, 因为

    29710

    现代 C++:一文读懂智能指针

    std::unique_ptr 的使用比较简单,也是用得比较多的智能指针。这里直接看例子。 使用裸指针时,要记得释放内存。...引用计数等共享资源的控制信息——实现上是维护一个指向控制信息的指针。 所以,shared_ptr 对象需要保存两个指针。...image 为什么控制信息和每个 shared_ptr 对象都需要保存指向共享资源的指针?可不可以去掉 shared_ptr 对象中指向共享资源的指针,以节省内存开销? 答案是:不能。...image 这种情况下,不用通过控制块中的指针,我们也能知道共享资源的位置——这个指针也可以省略掉。 ?...auto b = new Bar; auto sptr = b->shared_from_this(); 在我的环境下(gcc 7.5.0)上面的代码执行的时候会直接 coredump,而不是返回指向

    1.4K11

    c++11新特性之智能指针

    c++11引入了三种智能指针: std::shared_ptr std::weak_ptr std::unique_ptr shared_ptr shared_ptr使用了引用计数,每一个shared_ptr...(new int, [](int *p){ delete p; }); 关于shared_ptr有几点需要注意: • 不要用一个裸指针初始化多个shared_ptr,会出现double_free导致程序崩溃...• 通过shared_from_this()返回this指针,不要把this指针作为shared_ptr返回出来,因为this指针本质就是裸指针,通过this返回可能 会导致重复析构,不能把this指针交给智能指针管理...不要delete get()返回来的裸指针。 不是new出来的空间要自定义删除器。 要避免循环引用,循环引用导致内存永远不会被释放,造成内存泄漏。...作用1:返回this指针,上面介绍的shared_from_this()其实就是通过weak_ptr返回的this指针,这里参考我之前写的源码分析shared_ptr实现的文章,最后附上链接。

    83110

    再探 智能指针

    使用任何一项工具,都需要承担代价与风险的。 1、一个裸的指针不要用两个shared_ptr管理,unique_ptr也是,它们都会认为自己独占这个资源,你等释放的时候试试看。...3、当需要在类的内部接口中,如果需要将this作为智能指针来使用的话,需要用该类派生自enable_shared_from_this。...enable_shared_from_this和shared_from_this在构造和析构中是不能使用的,在某些情况下也不能使用,因为构造的时候类还未生成好,析构的时候类快完蛋了都没有意义。...关于这点自己实现一个智能指针就知道了。 一个shared_ptr在空间上至少是三个裸指针的大小(24个字节),本身有引用还要配合weak_ptr使用所以要保存多少该指针的引用。...由于unique_ptr的唯一性所以要转移资源可以transfer传值,只能调用obj的右值引用而不能用左值,transfer函数执行完就释放了,调用了transfer后原有的会变成空指针不再管理。

    29120

    CC++总结

    ::FreeConsole();//销毁控制台 枚举位运算  https://www.cnblogs.com/lixiaobin/p/EnumFlags.html  std::vector获取某一个位置的迭代器...加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。...由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。...,这个可宏是新的C99规范中新增的,             // 目前似乎gcc和VC6.0之后的都支持(VC6.0的编译器不支持)。            ...获取自身的std::shared_ptr 指针 继承自 std::enable_shared_from_this 调用 shared_from_this()  class FIniSection :

    77630
    领券