https://blog.csdn.net/nou_camp/article/details/70186721

在上一篇博客中提到了Auto_ptr(C++智能指针(一)),下面进行模拟实现Auto_ptr 
采用类模板实现

#include<iostream>
using namespace std;
template<class T>
class Autoptr
{
public:Autoptr(T* ptr = NULL):_ptr(ptr){}//Autoptr():_ptr(NULL)//{}Autoptr(Autoptr<T>& ap){this->_ptr = ap._ptr;ap._ptr = NULL;}Autoptr<T>& operator=(Autoptr<T>& sp){if (this != &sp){delete this->_ptr;_ptr = sp._ptr;sp._ptr = NULL;}return *this;}T* operator->(){return _ptr;}T operator*(){return *_ptr;}~Autoptr(){delete _ptr;_ptr = NULL;}void  Reset(T* ptr = 0){if (_ptr != ptr){delete  _ptr;}_ptr = ptr;}
protected:T* _ptr;
};void test()
{//int *p1 = new int(10);//Autoptr<int>ap1(p1);Autoptr<int> ap1(new int(10));//上面的两行代码可以直接用本行代码代替cout << *ap1 << endl;Autoptr<int> ap2(ap1);cout << *ap2 << endl;Autoptr<int> ap3(new int(20));ap3 = ap2;cout << *ap3 << endl;//cout << *ap1 << endl;//会使代码出错
}
int main()
{test();system("pause");return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

 


//cout << *ap1 << endl;//会使代码出错 
这是test函数中的代码,执行这句代码,会使程序崩溃,这是因为ap1已经把它指向的空间交给了ap2去管理,所以ap1已经不具备访问原来自己所指向的空间的权限。所以对它进行解引用是非法的。 
所以可以看清auto_ptr的本质是管理权的转移,即ap1将自己所指向的空间交给ap2来管理,析构也是由ap2来完成。


由上面可知auto_ptr有严重缺陷,所以后来有人写了scopedptr,慢慢发展形成了第三方库。 
scopedptr ->防拷贝,意思就是不能进行拷贝,简单地说是一种简单粗暴的方式。下面模拟实现scopedptr。采用模板类实现。

template<class T>
class scopedptr
{
public:scopedptr(T *ptr):_ptr(ptr){}T* operator->(){return _ptr;}T operator*(){return *_ptr;}~scopedptr(){delete _ptr;_ptr = NULL;}
protected:scopedptr<T>& operator=(const scopedptr<T>& s);scopedptr(scopedptr<T>& ap);
private:T* _ptr;
};
void test()
{scopedptr<int> s1(new int(10));//scopedptr<int> s2(s1);//有错误,编译不通过cout << *s1 << endl;
}
int main()
{test();system("pause");return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

scopedptr中对拷贝构造函数和赋值运算符的重载函数只是进行了声明,并没有去定义这两个函数,而且声明为protected或者是private,这是防止别人在类外对这两个函数进行定义。防止拷贝,所以说scopedptr是一种简单粗暴的方式。


编写程序往往要用到拷贝,这样scopedptr就不能起到相应的作用,所以便有了shared_ptr。 
shared_ptr->采用了引用计数,优点是功能强大,但是也有缺点,缺点是过于复杂,而且会引起循环引用。 
下面模拟实现shared_ptr

#include<iostream>
using namespace std;
template<class T>
class sharedptr
{
public:sharedptr(T* ptr) //构造:_ptr(ptr), _refcount(new int(1)){}sharedptr() //构造:_ptr(NULL), _refcount(new int(1)){}sharedptr(const sharedptr<T>& sp) //拷贝构造:_ptr(sp._ptr), _refcount(sp._refcount){(*_refcount)++;}sharedptr<T>& operator=(const sharedptr<T>& sp) //赋值运算符的重载{if (_ptr != sp._ptr){delete _ptr;delete _refcount;_ptr = sp._ptr;_refcount = sp._refcount;++(*_refcount);}return *this;}~sharedptr() //析构{Realease();}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T Getrefcount(){return *(_refcount);}inline void Realease(){if (--*_refcount == 0){delete _refcount;delete _ptr;}}void  Reset(T* ptr ,T* refcount){if (_ptr != ptr){delete  _ptr;delete _refcount;}_ptr = ptr;_refcount = refcount;}
public:T* _ptr;T* _refcount;//T _refcount;//有缺陷//int static _refcount;//有缺陷
};
void test()
{sharedptr<int> s1(new int(10));//cout << *s1._refcount << endl;cout << s1.Getrefcount() << endl;sharedptr<int> s2(s1);//cout << *s2._refcount << endl;cout << s2.Getrefcount() << endl;sharedptr<int> s3(new int(20));s3 = s1;//cout << *s3._refcount << endl;cout << s3.Getrefcount() << endl;
}
int main()
{test();//*sharedptr<int> sp;  // 验证Reset//sp.Reset(new int,new int(1));       //*sp = 10;//cout << *sp << endl;//sp.Reset(new int, new int(1));  //*sp = 20;//cout << *sp << endl;//sp.Reset(); system("pause");return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

C++智能指针(二)模拟实现三种智能指针相关推荐

  1. python miio 连接小米网关_智能家居沟通不再难,小米米家智能多模网关发布,三种协议全支持...

    智能家居产品面世很多年了,从期待中的红火到现在的不温不火,其中一个重要的原因就在于各个产品使用不同的协议.不用厂商根据不同的考量,有的选择了Zigbe协议,有的选了WiFi,而有的则选择了蓝牙.这样的 ...

  2. CCF-CSP 201903-2二十四点 三种方法 满分题解 结尾附惊天方法

    CCF-CSP 201903-2二十四点 三种方法 满分题解 结尾附惊天方法 题目链接:CCF-CSP 201903-2二十四点 方法一思路: 1.通读题意,发现该表达式仅由4个数字和3个四则运算组成 ...

  3. AutoCAD二次开发三种添加插件按钮的方法

    在上一篇关于AutoCAD的文章中,我将很多关于CAD的博客相关资源进行了说明,这一篇文章我将介绍如何在AutoCAD中的ribbon中添加相应的按钮.就是下面这种按钮: PS:在开发中我们最好使用中 ...

  4. AutoCAD二次开发三种添加插件按钮的方法之二

    上一篇相关文章主要借助了cuix配置文件来制作插件按钮,但是对于纯码农来说还是喜欢以代码来说话,今天这篇文章就来讲讲纯代码添加按钮. 开发IDE:VS2010 环境:.Net Framework4.0 ...

  5. 三种函数指针的表达以及函数指针概念讲解

    三种函数指针的表达以及函数指针概念讲解 函数指针的概念 三种表达函数指针的方法 函数指针的概念 如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为 ...

  6. C++中的三种智能指针分析(RAII思想)

    2019独角兽企业重金招聘Python工程师标准>>> 智能指针 首先我们在理解智能指针之前我们先了解一下什么是RAII思想.RAII(Resource Acquisition Is ...

  7. strcpy和strncpy的使用以及strcpy的模拟实现(三种方法)

    前言:Hello!大家好,我是@每天都要敲代码:上一讲对于strlen库函数的使用和三种模拟实现方法相信大家都很熟悉了,strlen库函数是用来求字符串的长度,遇到'\0'终止:所需头文件是<s ...

  8. java二维数组三种初始化方法(实例)

    初始化方法: 1.使用大括号直接赋值,适合已经确定知道数组元素的情况 2.给定二维数组的大小 3.数组第二维的长度可变化,未改变 代码举例如下: public class NewArray {publ ...

  9. 华为Android10版怎么截屏,华为Mate 10怎么截屏 三种智能截屏方式图文教程

    相信所有用户在使用手机的过程中都会使用到截屏功能,那么在华为新款旗舰Mate10 上如何截屏,共有哪些截屏方式呢?下面就让小编给大家带来最详细的Mate10 智能截屏教程. 相信,华为的老用户们应该都 ...

最新文章

  1. Pandas 基础 (4)—— 汇总和计算描述统计
  2. 基于 Prometheus、InfluxDB 与 Grafana 打造监控平台
  3. 洛谷——P1177 【模板】快速排序
  4. Lead saved query bug
  5. 在CentOS6.5上安装Tomcat7
  6. 数据库学习建议之提高数据库速度的十条建议
  7. 我被“非结构化数据包围了”,请求支援!
  8. 微信公众平台开发之留言板
  9. mysql数据表设计 对应成二维数组_结果集数据怎么转换成二维数组
  10. 系统学习数字图像处理之图像压缩
  11. 【原】数据库排序规则导致的问题
  12. 为什么有些程序员明明很努力,但是却回报很低,收益很小,工资始终上不去-出自中华石杉老师
  13. c8网络语言意思,2013年十大网络流行语
  14. C盘扩容,解决电脑卡顿
  15. 中专计算机专业包括哪些方面,中专计算机有什么专业?
  16. nginx: [emerg] unexpected “}”
  17. UA MATH564 概率分布2 Poisson分布
  18. 自然语言处理NLP星空智能对话机器人系列:深入理解Transformer自然语言处理 Training a GPT-2 language model Steps 7 to 9
  19. INS防封号技巧,这些注意事项如果你不知道容易被封号停用
  20. 【渝粤题库】广东开放大学 企业文化学 形成性考核

热门文章

  1. Ansible: hosts文件拆分为inventory和定义inventory全局变量
  2. Django集合Ueditor
  3. 替换Quartus 自带编辑器 (转COM张)
  4. Hibernate 笔记4 实现对数据库的增删改查
  5. 获取clientheight为0_用10行python代码获取全国城市交通生活圈
  6. svgaps绘制时不能用中文命名吗_设计师需要了解的切图命名规范
  7. 微型计算机接口与技术的交通灯,微机原理及接口技术课程设计交通灯
  8. android studio smssdk,SMSSDK for Android 配置
  9. java弹出虚拟键盘_JS实现电脑虚拟键盘的操作
  10. 《线程管理:线程基本操作》