博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++智能指针(二)模拟实现三种智能指针
阅读量:4096 次
发布时间:2019-05-25

本文共 5052 字,大约阅读时间需要 16 分钟。

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

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

采用类模板实现

#include
using namespace std;template
class Autoptr{public: Autoptr(T* ptr = NULL) :_ptr(ptr) {} //Autoptr() :_ptr(NULL) //{} Autoptr(Autoptr
& ap) { this->_ptr = ap._ptr; ap._ptr = NULL; } Autoptr
& operator=(Autoptr
& 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
ap1(p1); Autoptr
ap1(new int(10));//上面的两行代码可以直接用本行代码代替 cout << *ap1 << endl; Autoptr
ap2(ap1); cout << *ap2 << endl; Autoptr
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 scopedptr{public: scopedptr(T *ptr) :_ptr(ptr) {} T* operator->() { return _ptr; } T operator*() { return *_ptr; } ~scopedptr() { delete _ptr; _ptr = NULL; }protected: scopedptr
& operator=(const scopedptr
& s); scopedptr(scopedptr
& ap);private: T* _ptr;};void test(){ scopedptr
s1(new int(10)); //scopedptr
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
using namespace std;template
class sharedptr{public: sharedptr(T* ptr) //构造 :_ptr(ptr), _refcount(new int(1)) {} sharedptr() //构造 :_ptr(NULL), _refcount(new int(1)) {} sharedptr(const sharedptr
& sp) //拷贝构造 :_ptr(sp._ptr), _refcount(sp._refcount) { (*_refcount)++; } sharedptr
& operator=(const sharedptr
& 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
s1(new int(10)); //cout << *s1._refcount << endl; cout << s1.Getrefcount() << endl; sharedptr
s2(s1); //cout << *s2._refcount << endl; cout << s2.Getrefcount() << endl; sharedptr
s3(new int(20)); s3 = s1; //cout << *s3._refcount << endl; cout << s3.Getrefcount() << endl;}int main(){ test(); //*sharedptr
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

这里写图片描述

你可能感兴趣的文章
19 个 JavaScript 常用的简写技术
查看>>
iOS应用间相互跳转
查看>>
iOS开发之支付宝集成
查看>>
iOS开发 支付之银联支付集成
查看>>
iOS开发支付集成之微信支付
查看>>
浅谈JavaScript--声明提升
查看>>
React非嵌套组件通信
查看>>
Websocket 使用指南
查看>>
浏览器兼容性问题解决方案 · 总结
查看>>
一个很棒的Flutter学习资源列表
查看>>
为什么你应该放弃React老的Context API用新的Context API
查看>>
Koa2初体验
查看>>
Koa 2 初体验(二)
查看>>
Koa2框架原理解析和实现
查看>>
vue源码系列文章good
查看>>
你不知道的Virtual DOM
查看>>
VUE面试题总结
查看>>
写好JavaScript条件语句的5条守则
查看>>
原生JS中DOM节点相关API合集
查看>>
【TINY4412】U-BOOT移植笔记:(7)SDRAM驱动
查看>>