/*
代码分析: 这是标准库的源码,我们看到在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始终是无效。 同理在析构函数中也不能调用shared_from_this()。
在析构时,引用计数已经变为零,weak_ptr已经相当于指向的是一个无效的对象,这是不能通过此无效的weak_ptr构造shared_ptr。 */ 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);
}
/* 智能指针shared_from_this崩溃问题分析 */

#include <iostream>
#include <memory> class TestClass : public std::enable_shared_from_this<TestClass>
{
public:
TestClass()
{
}
~TestClass()
{
} void show()
{
printf("hello world .\n");
} std::shared_ptr<TestClass> getPtr()
{
return shared_from_this();
}
}; int main()
{
TestClass t;
t.getPtr(); //shared_from_this()错误 TestClass* t1(new TestClass());
t1->getPtr();//shared_from_this()错误 std::shared_ptr<TestClass> t2(new TestClass());
t2->getPtr(); //正确,已提前创建了shared_ptr
}

C++ 智能指针五的更多相关文章

  1. 必须要注意的 C++ 动态内存资源管理(五)——智能指针陷阱

    必须要注意的 C++ 动态内存资源管理(五)——智能指针陷阱 十三.小心使用智能指针.         在前面几节已经很详细了介绍了智能指针适用方式.看起来,似乎智能指针很强大,能够很方便很安全的管理 ...

  2. 【C++】智能指针简述(五):解决循环引用的weak_ptr

    总结一下前文内容: 1.智能指针通过RAII方法来管理指针:构造对象时,完成资源初始化;析构对象时,对资源进行清理及汕尾. 2.auto_ptr,通过“转移所有权”来防止析构一块内存多次.(如何转移? ...

  3. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  4. c++ auto_ptr智能指针

    c++ auto_ptr智能指针 该类型在头文件memory中,在程序的开通通过 #include<memory> 导入,接下来讲解该智能指针的作用和使用. 使用方法: auto_ptr& ...

  5. Android智能指针sp wp详解

    研究Android的时候,经常会遇到sp.wp的东西,网上一搜,原来是android封装了c++中对象回收机制.说明:1. 如果一个类想使用智能指针,那么必须满足下面两个条件:    a. 该类是虚基 ...

  6. STL模板_智能指针概念

    一.智能指针1.类类型对象,在其内部封装了一个普通指针.当智能指针对象因离开作用域而被析构时,其析构函数被执行,通过其内部封装的普通指针,销毁该指针的目标对象,避免内存泄露.2.为了表现出和普通指针一 ...

  7. 论C++的智能指针

    一.简介   参考这篇博客,并且根据<C++ Primer>中相关知识,我总结了C++关于智能指针方面的内容.   为了解决内存泄漏的问题,便出现了智能指针.STL提供的智能指针有:aut ...

  8. DirectX11--ComPtr智能指针

    综述 DirectX11 With Windows SDK完整目录 欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报. IUnknown接口类 DirectX ...

  9. c/c++ 智能指针 shared_ptr 和 new结合使用

    智能指针 shared_ptr 和 new结合使用 用make_shared函数初始化shared_ptr是最推荐的,但有的时候还是需要用new关键字来初始化shared_ptr. 一,先来个表格,唠 ...

随机推荐

  1. bzoj1563: [NOI2009]诗人小G 决策单调性(1D1D)

    目录 题目链接 题解 代码 题目链接 bzoj1563: [NOI2009]诗人小G 题解 \(n^2\) 的dp长这样 \(f_i = min(f_j + (sum_i - sum_j - 1 - ...

  2. [__NSArrayM insertObject:atIndex:]: object cannot be nil'

    错误描述:如下图 分析原因: 1.插入的对象为空了 2.[__NSSetM addObject:] object cannot be nil [__NSArrayM insertObject:atIn ...

  3. CocosCreator的节点显示和隐藏

    隐藏和显示有两种方式: 1.禁止节点node的运行,方法是x.node.active=false[此时隐藏了节点,且节点不再运行];恢复节点正常运行,x.node.active=true;或者使用x. ...

  4. kaggle PredictingRedHatBusinessValue 简单的xgboost的交叉验证

    PredictingRedHatBusinessValue 这个超级简单的比赛 随手在一个kernels上面随便改了改,交叉验证的xgboost: 感觉还是稍微有一点借鉴意义的(x 注释的部分是One ...

  5. google ctemplate——c++模板引擎

    1 概述 在进行web开发时,使用传统的CGI方式,在C/C++程序里面既要处理逻辑,也要处理页面显示内容,会比较混乱.可以通过模板引擎,使得逻辑与显示的分离.Google CTemplate就是其中 ...

  6. linux -- 查看磁盘空间的大小

    Ubuntu 查看磁盘空间大小命令 df -h Df命令是linux系统以磁盘分区为单位查看文件系统,可以加上参数查看磁盘剩余空间信息, 命令格式: df -hl  显示格式为:  文件系统 容量 已 ...

  7. windows Server 2008 R2的安装

    1.http://msdn.itellyou.cn/ 在此下载IOS文件. 2.通过Nero进行刻录系统光盘,可以通过Daemon直接加载IOS,然后复制就可以了. 3.通过开机 Delete键进BI ...

  8. iOS开发-UIImageView高效设置Radius

    圆角的设置在iOS中随处可见,开发的时候也很方便,但是有的时候如果一个页面有大量的需要设置圆角的图片,容易产生性能问题,UIImageView ios9.0之前设置圆角是会产生离屏渲染的,9.0之后不 ...

  9. Spark:实现行转列

    示例JAVA代码: import static org.apache.spark.sql.functions.col; import static org.apache.spark.sql.funct ...

  10. 【转发】centos 7开启FTP以及添加用户配置权限,只允许访问自身目录,不能跳转根目录

    1.切换到root用户 2.查看是否安装vsftp,我这个是已经安装的. [root@localhost vsftpd]# rpm -qa |grep vsftpd vsftpd-3.0.2-11.e ...