C++11的enable_shared_from_this

C++11中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 阅读详情

c++11 中的 shared_from_this() 来源于 boost 中的 enable_shared_form_this 类和 shared_from_this() 函数,功能为返回一个当前类的 std::share_ptr,使用方法如下:

#include<memory>
class Test: public std::enable_shared_from_this<Test>
{
public:  
    Test();
    ~Test();
    std::shared_ptr<Test> getSharedFromThis() { return shared_from_this(); }
}

enable_shared_from_this 的由来

在智能指针的使用过程中,我们会遇到这样一种情况,我们在类的成员函数调用某一个函数,而该函数需要传递一个当前对象的智能指针作为参数时,我们需要能够在成员函数中获得自己的智能指针。

在多线程程序中也存在这样的应用,如果我们的线程函数是一个成员函数,可以把该对象的智能指针作为参数传递到线程函数中,这种做法是人为的增加了对象的引用计数,延长对象的生命周期,防止线程函数在执行的时候对象被释放而引发内存错误。总之就是我们在实际的编码中会存在各种各样的应用。

我们可能有两个疑惑:

  1. 把当前类对象作为参数传给其他函数时,为什么要传递 share_ptr 呢?直接传递 this 指针不可以吗?

    一个裸指针传递给调用者,谁也不知道调用者会干什么?假如调用者 delete 了该对象,而 share_tr此时还指向该对象。

  2. 这样传递 share_ptr 可以吗?share_ptr<this> ?

    这样会造成2个非共享的share_ptr指向一个对象,最后造成2次析构该对象。

我们不能人为地通过 this 来构造一个当前对象的 shared_ptr 指标,如下错误的做法:

#include <memory>
class TestClass;

void Test(std::shared_ptr<TestClass> tt)
{

}

class TestClass
{
public:
    TestClass() {}    
    ~TestClass() {}
    void TestPtr()
    {
        std::shared_ptr<TestClass> tt = std::shared_ptr<TestClass>(this);
        Test(tt);
    }
};

int main(int argc, char** argv)
{
    std::shared_ptr<TestClass> t(new TestClass());
    t->TestPtr();
    return 0;
}

在 TestPtr() 函数中通过 this 构造出 shared_ptr,就相当于把自己的的控制权交给了这个临时变量 tt,一旦 tt 超出作用域就会释放,导致该对象也被释放。这是一个致命的错误。

为了解决这个问题,在 C++11 中提供了 enable_shared_from_this 这个模板类(boost 库很早就提供了这个模板类),自己的对象继承自 enable_shared_from_this 。enable_shared_from_this 提供了一个shared_from_this() 的方法返回自己的智能指针。与上面错误的例子区别在于,shared_from_this 会增加该对象的引用计数,而不是重新建立一个临时的 shared_ptr 来管理。看下面具体的例子:

#include <memory>
class TestClass;

void Test(std::shared_ptr<TestClass> tt)
{

}

class TestClass : public std::enable_shared_from_this<TestClass>
{
public:
    TestClass() {}    
    ~TestClass() {}
    void TestPtr()
    {
        std::shared_ptr<TestClass> tt = shared_from_this();
        Test(tt);
    }
};

int main(int argc, char** argv)
{
    std::shared_ptr<TestClass> t(new TestClass());
    t->TestPtr();
    return 0;
}

shared_from_this() 函数

shared_from_this 的出现确实能够解决我们编码中所遇到的问题,但是它的坑也是比较多的。我们先来看看 enable_shared_from_this 这个对象:

template<class _Ty> 
class enable_shared_from_this
{	// provide member functions that create shared_ptr to this
public:
    typedef _Ty _EStype;

    shared_ptr<_Ty> shared_from_this()
    { // return shared_ptr
        return (shared_ptr<_Ty>(_Wptr));
    }

    shared_ptr<const _Ty> shared_from_this() const
    { // return shared_ptr
        return (shared_ptr<const _Ty>(_Wptr));
    }

protected:
    enable_shared_from_this()
    {	// construct (do nothing)
    }

    enable_shared_from_this(const enable_shared_from_this&)
    {	// construct (do nothing)
    }

    enable_shared_from_this& operator=(const enable_shared_from_this&)
    {	// assign (do nothing)
        return (*this);
    }

    ~enable_shared_from_this()
    {	// destroy (do nothing)
    }

private:
    template<class _Ty1, class _Ty2>
    friend void _Do_enable(
            _Ty1 *,
            enable_shared_from_this<_Ty2>*,
            _Ref_count_base *);

    mutable weak_ptr<_Ty> _Wptr;
};

template<class _Ty1, class _Ty2>
inline void _Do_enable(
    		_Ty1 *_Ptr,
            enable_shared_from_this<_Ty2> *_Es,
            _Ref_count_base *_Refptr)
{ // reset internal weak pointer
    _Es->_Wptr._Resetw(_Ptr, _Refptr);
}

这是标准库的源码,我们看到在 enable_shared_from_this 内部储存了一个 weak_ptr。shared_from_this 函数就是通过这个 weak_ptr 得到了。但是另外一点,我们可以看到在enable_shared_from_this 的构造函数中并没有对这个 weak_ptr 进行初始化。

这就是为什么我们不能在构造函数调用 shared_from_this() 的原因,因为其内部的 weak_ptr 并没有初始化。所以会产生错误。

在实际的程序设计中如果我们需要在对象初始化中用到自己的 shared_ptr。可以单独将初始化操作放到一个独立的 init 函数中,这时候再调用 shared_from_this() 是没有问题的(但还是有点问题,下面会讲到)

熟悉 weak_ptr 的同学可能知道,我们在使用 weak_ptr 前,需要用一个 shared_ptr 来对其进行初始化。对 weak_ptr 初始化是要能获取到当前对象的引用计数对象,而引用计数对象可以通过 shared_ptr 对象获取到。当然我们同样可以用一个已经初始化过的 weak_ptr 来初始化另一个 weak_ptr,因为已初始化的weak_ptr 也可能获取到对象的引用计数。

enable_shared_from_this 内部的 weak_ptr 是通过_Do_enable函数初始化的。而_Do_enable函数实在shared_ptr 的构造函数中调用的,这是至关重要的一个环节。正因为如此我们在调用 shared_from_this 之前请确保程序已经显式地建立了 shared_ptr 对象,要不然enable_shared_from_this 内部的 weak_ptr 始终是无效。

下面具体举例说明的:

class TestClass : public std::enable_shared_from_this<TestClass>
{
public:
    TestClass()
    {
    }
    ~TestClass()
    {
        //TestClassPtr tt = shared_from_this();
    }
    void TestPtr()
    {
        std::shared_ptr<TestClass> tt = shared_from_this();
        Test(tt);
    }
};

int main()
{
    TestClass t;
    t.TestPtr(); //shared_from_this()错误

    TestClass* t1(new TestClass());
    t1->TestPtr();//shared_from_this()错误

    std::shared_ptr<TestClass> t2(new TestClass());
    t2->TestPtr(); //正确,已提前建立了shared_ptr
}

同理在析构函数中也不能调用 shared_from_this()。

在析构时,引用计数已经变为零,weak_ptr 已经相当于指向的是一个无效的对象,不能通过此无效的 weak_ptr 构造 shared_ptr。

C++ std::enable_shared_from_this 类模板到底有什么用?【 C++11 标准中正式引入】 本文介绍了C++中std::enable_shared_from_this模板的用法,通过HttpServer示例说明其重要性。在异步回调中直接使用this指针可能导致对象提前销毁引发未定义行为,而shared_from_this()通过共享所有权确保对象生命周期延长到异步操作完成。文章分析了其工作原理:shared_from_this()会创建新的shared_ptr副本,增加引用计数,直到回调执行完毕才可能释放对象。该模板是解决异步操作中对象生命周期问题的标准工具,能有效防止悬空指针问题。 阅读详情

相关推荐

《统计学习方法》——李航 学习大纲

最近在学习李航写的统计学习方法概论, 每一章都用xmind理清了思路,括号里是书里的公式,第一次写博文,敬请指教~~~~ 第一章 统计学习方法论 第二章 感知机 每个方法其实只需要着重掌握三要素和输入输出就可以了,主要看模型、策略和算法。 感知机主要是二类分类的线性分类模型。 看到后面会注意感知机和支持向量机的区别。 第三章 k近

wjy619251334的博客 1万+

shared_from_this() 实现原理

shared_from_this() 实现原理 shared_ptr 实现原理 作用 C++中采用new和delete来申请和释放内存,但如果管理不当,很容易出现内存泄漏 std::shared_ptr, std::unique_ptr, std::weak_ptr,三种智能指针类,可以自动管理内存 使用示例 智能指针对象,和一般的指针用法几乎完全相同 #include <iostream> #include <memory> // 需要包含这个头文件 int main(

weixin_40058501的博客 654

Kindle电子书DRM破解全攻略:从下载到转换的完整流程(含最新DeDRM插件配置)

本文详细介绍了如何合法移除个人购买的Kindle电子书的DRM保护,实现跨设备阅读与备份。核心内容包括使用最新DeDRM插件(如noDRM分支)配合Calibre进行配置,并针对亚马逊最新的KFX加密格式提供了密钥提取与实战操作指南。文章强调该方法仅适用于个人合理使用,旨在帮助读者真正掌控自己的数字资产。

delta的博客 575

enable_shared_from_this模板类使用完全解析

转自:http://hahaya.github.io/use-enable-shared-from-this/ enable_shared_from_this模板类使用完全解析 作者:hahaya 日期:2013-11-28 以前都没有用过enable_shared_from_this模板类,虽然经常遇到但是也没怎么去关注,今天抽时间好好学习了下enable_share

martin_liang的专栏 2873

保姆级教程:在Windows上用Python+OpenCV调用海康工业相机(附MVS配置避坑指南)

本文提供了一份详细的Windows环境下使用Python和OpenCV调用海康工业相机的保姆级教程,涵盖MVS配置避坑、相机连接、图像获取与格式转换等关键步骤。特别针对工业相机取流中的常见问题,如独占访问控制和多相机协同工作,提供了实用解决方案,帮助开发者快速实现稳定的图像采集系统。

weixin_29228781的博客 398

手把手教你用CubeMX给GD32F103点灯、调串口(附完整工程)

本文详细介绍了如何使用CubeMX为GD32F103开发板配置GPIO点灯和串口通信,包含完整的工程创建、代码构建和测试流程。特别强调了GD32与STM32的差异点及常见避坑技巧,帮助开发者快速上手GD32开发。

weixin_42566424的博客 313

析构函数中不可以使用shared_from_this()

参考:https://www.icode9.com/content-4-492133.html 析构函数中不能直接使用 shared_from_this() #include <memory> #include <iostream> struct A : public std::enable_shared_from_this<A> { ~A() { auto this_ptr = shared_from_this(); // std::b

poinsettia的专栏 794

IEEE802.11bf: WLAN Sensing Standard

下表为IEEE802.11bf 定义的使用情境 (Use Cases)

qinsd19的博客 1054

c++11之std::enable_shared_from_this入门

一、std::enable_shared_from_this&lt;T&gt;应用场景 在记录std::enable_shared_from_this之前,需要先看一下原始指针与shared_ptr在使用过程中一些问题。 先看一代码段: #include &lt;QCoreApplication&gt; #include &lt;memory&gt; #include &lt;i...

ypy9323的博客 1438

AutoSAR系列讲解 - 资料下载

学习资料下载汇总

雪云飞星的博客 4万+

零停机更新黑科技:Spring Boot应用实现无缝升级的实战指南

本文介绍了基于Spring Boot和Tomcat实现零停机更新的技术方案,通过动态端口切换和优雅关闭机制,确保服务更新过程中业务不中断。文章详细解析了核心原理,包括内嵌Tomcat的工作机制、零停机更新的三大技术基石(端口动态切换、优雅关闭和进程接管)。同时提供了完整的Java实现代码,重点展示了端口动态检查、参数动态调整、旧进程优雅终止等关键逻辑。该方案适用于高可用系统升级场景,能够有效避免传统部署方式导致的服务中断问题,实现100%无感知的应用更新。

墨夶的博客 818

c++ enable_shared_from_this

智能指针 ptr1 和 ptr2 的引用计数都是 1,说明它们指向的不是同一个资源(这里可能会有人疑惑两个智能指针指向同一个地址,怎么引用计数没有增加呢?类 A 中有一个函数 getSharedPtr() 函数,用于返回指向当前对象的一个智能打针,就是用 this 构造了一个智能指针进行返回,我们看一下这样会不会有问题呢?我们看到,两个智能指针的引用计数都为2,这两个智能指针指向了相同的资源,在 main 函数退出后,两个智能指针释放,引用计数变为 0,资源释放正常。执行没有异常,那这样用是正确的吗?

tianyexing2008的博客 3102

链接文件及功能安全:S32K3如何将FLASH驱动放到RAM里面、RAM如何实现软件复位数据不丢失操作。

在通过RTD的SDK也好MCAL也好,始终存在一个问题,生成的代码除了看门狗模块,默认都是放在flash里面,按照正常逻辑来看没啥大的问题,思考一个问题:Flash放在0x100的位置,但是此时我们要操作0x100怎么办?那肯定不允许啊,但是将flash的驱动放在RAM里面就可以避免这个问题的产生。Flash的特性:PF0能操作PF1,当然PF1也能操作PF0的,以此类推,只要不操作自身,想怎么玩都可以。这也是一个物理特性吧。

梦想技术家 2310

c++11 std::enable_shared_from_this

上面程序可以看出以下几个方面。

u011743621的博客 708

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C++ 11的enable_shared_from_this

C++ 11的提供了一个模板类std::enable_shared_from_this。 目的 为安全获取当前对象的shared_ptr提供方便。 原因 一般在对象的函数中,是不可以返回一个指向this指针的shared_ptr。因为如果当前对象已经析构,当shared_ptr再次析构时,因为其管理的指针已经不再合法,所以会导致Undefined行为。 如果实在有这种需求,就应该使用std::enable_shared_from_this提供的shared_from_this方法获取。 使用 class S

大数据时代的狂欢 490

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【C++ 11】 std::enable_shared_from_this

C++11 std::enable_shared_from_this 一 介绍 1 申明 std::enable_shared_from_this template< class T > class enable_shared_from_this;(C++11 起) std::enable_shared_from_this 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1

qq_43331089的博客 455

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【转载】C++11中enable_shared_from_this的用法解析

C++11 开始支持 enable_shared_from_this,它是一个模板类,定义在头文件 ,其原型为:std::enable_shared_from_this 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, … ),它们与 pt 共享对象 t 的所有权。

好好学习,天天向上~ 536

C++11中模板类std::enable_shared_from_this的使用

C++11中的模板类template <class T> class enable_shared_from_this功能:允许从std::enable_shared_from_this派生的类T的对象创建指向自身的shared_ptr实例并与现有的shared_ptr对象共享所有权。T需要为完整类型,通常是final的。如果使用this创建一个新的shared_ptr,则其与现有的shared_ptr所有者不同,从而会导致无效引用或导致此对象被删除多次。 std::...

网络资源是无限的 1745

c++11 智能指针-辅助类 (std::enable_shared_from_this)

std::enable_shared_from_this 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。

qq_40788199的博客 2040

c++11之enable_shared_from_this

enable_shared_from_this的主要作用是用来安全地获取指向这个类(即继承enable_shared_from_this模板的类)的指针,有人会说,c++类不是都有默认的this用来指向这个类吗,何必还要再采用enable_shared_from_this的方法呢,大家先从一个例子来看用this指针会存在的问题: #include<memory> #include&...

songlipeng的专栏 899

C++11 enable_shared_from_this

enable_shared_from_this是一个模板类,定义于头文件,其原型为: template< class T > class enable_shared_from_this; std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_p...

xupeng1644的博客 1385

C++11 enable_shared_from_this<>与shared_from_this()

智能指针的有关函数使用注意智能指针分类shared_from_this()函数demo测试是否真正理解 智能指针分类 unique_ptr unique_ptr是个独占指针,C++ 11之前就已经存在,unique_ptr所指的内存为自己独有,某个时刻只能有一个unique_ptr指向一个给定的对象,不支持拷贝和赋值。 #include <iostream> #include <string> #include <memory> #include <vecto

lzh824359508的博客 509

[C++11]enable_shared_from_this

学习资料网址 C++11新特性之十:enable_shared_from_this https://blog.youkuaiyun.com/caoshangpa/article/details/79392878 作用: std::enable_shared_from_this 能让一个对象pt安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。 (理解:pt pt1 pt2是同一个对象,且对这个...

willis 245

[C++11] enable_shared_from_this

enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shared_from_this; std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对...

destiny的专栏 216

C++11新特性之十:enable_shared_from_this

enable_shared_from_this是一个模板类,定义于头文件&lt;memory&gt;,其原型为:template&lt; class T &gt; class enable_shared_from_this;       std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管...

草上爬的博客 10万+

C++11 std::enable_shared_from_this

一 介绍 1 申明 std::enable_shared_from_this template&lt; class T &gt; class enable_shared_from_this;(C++11 起) std::enable_shared_from_this 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std...

程序员Link 1258
上一篇: 条件变量中pthread_cond_wait函数
下一篇: C++编译优化RVO&NRVO&复制省略
「已注销」
博客等级 码龄7年 22粉丝 160原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值