再谈智能指针
Posted 逸马闪骑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了再谈智能指针相关的知识,希望对你有一定的参考价值。
http://www.cnblogs.com/lewiskyo/p/4214592.html 之前写过一篇文章介绍智能指针,并且简单实现了auto_ptr.
里面提到 auto_ptr 不能做为Stl容器的元素,原因具体是 http://www.360doc.com/content/14/0429/16/1317564_373230218.shtml
简要来说就是在对Stl容器元素进行复制构造时,不能改变原来的值(const T2& value),而auto_ptr在复制构造的时候,一定会修改元素的值(即将指向实际内存地址的指针置NULL),否则就会两个指针指向同一个地址,当析构的时候就会出现重复析构。
所以是赋值函数出了问题。
但如果仅使用构造函数,则是没问题的,如这里的例子 http://www.cnblogs.com/lewiskyo/p/4604839.html
而在引入shared_ptr后,这些问题都解决了,因为shared_ptr增加了引用数量这个变量。
这里想简单实现下 shared_ptr, 代码基于 http://www.cnblogs.com/yangshaoning/archive/2012/03/18/cpp_smart_pointer.html
这里加上了模板,代码如下:
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 6 template <typename T> class SmartPtr; 7 8 template<typename T> 9 class RefPtr 10 { 11 friend class SmartPtr<T>; 12 13 RefPtr(T *pointer = NULL):t( pointer), count(1) 14 { 15 } 16 17 ~RefPtr() 18 { 19 cout << "destructor delete refptr" <<endl; 20 delete t; 21 } 22 23 T *t; 24 int count; 25 26 }; 27 28 29 template<typename T> 30 class SmartPtr 31 { 32 public: 33 34 // 为了兼容stl预分配空间使用默认构造函数 35 SmartPtr() 36 { 37 rp = NULL; 38 } 39 40 SmartPtr( T* object): rp(new RefPtr<T>(object)) 41 { 42 } 43 44 SmartPtr(const SmartPtr& rhs) 45 { 46 // 为了兼容stl预分配空间使用默认构造函数时,rp = NULL 47 if ( rhs.rp != NULL) 48 { 49 rp = rhs.rp; 50 ++rp->count; 51 } 52 } 53 54 SmartPtr& operator=(const SmartPtr &rhs) 55 { 56 if(this == &rhs) 57 return *this; 58 59 if (rp) 60 { 61 --rp->count; 62 if (rp->count == 0) 63 delete rp; 64 } 65 66 67 rp = rhs.rp; 68 ++rp->count; 69 70 return *this; 71 } 72 73 ~SmartPtr() 74 { 75 if (rp) 76 { 77 --rp->count; 78 if (rp->count == 0) 79 delete rp; 80 } 81 82 } 83 84 private: 85 RefPtr<T> *rp; 86 }; 87 88 89 int main() 90 { 91 92 { 93 SmartPtr<int> s1(new int(10)); 94 SmartPtr<int> s2(s1); 95 96 SmartPtr<int> s3 (new int (20)); 97 s3 = s1; 98 } 99 100 cout << "operator v1" << endl; 101 102 { 103 vector<SmartPtr<int> > v1; 104 v1.push_back(SmartPtr<int>(new int (10))); 105 v1.push_back(SmartPtr<int>(new int (10))); 106 v1.push_back(SmartPtr<int>(new int (10))); 107 v1.push_back(SmartPtr<int>(new int (10))); 108 } 109 110 cout << "operator v1 end" << endl; 111 112 cout << "operator v2" << endl; 113 114 { 115 vector<SmartPtr<int> > v2(10); 116 v2[0] = SmartPtr<int>(new int (10)); 117 v2[1] = SmartPtr<int>(new int (20)); 118 v2[2] = SmartPtr<int>(new int (30)); 119 v2[3] = SmartPtr<int>(new int (40)); 120 } 121 122 cout << "operator v2 end" << endl; 123 }
这里不管是Stl的构造函数,还是赋值函数都没问题了。
几个注意点:
1. 第六行需要前置声明SmartPtr,否则RefPtr会识别不了这个友元.
2. RefPtr::count仅在SmartPtr内改变值,所有指向同一个对象的SmartPtr操作同一个count。
3. SmartPtr::rp仅是一个指针,若然多个SmartPtr指向同一个对象,那么多个SmartPtr::rp则共享同一份地址,当SmartPtr析构时,--count,count==0时要 delete rp, 释放rp指向的地址,其他情况不必delete,只需要让系统回收rp指针所占用的地址即可。
后话:
拿别人代码改造实现过程中有几个基础知识点值得在这里提一下的,也是提醒自己。
1. 代码114行, vector<SmartPtr<int> >v2(10). 这里是常见的给vector预分配空间的做法,实际上是 调用10次 SmartPtr<int>() 默认构造函数得到10个实例放到容器里面。 代码116到119行, 执行SmartPtr的赋值函数,但此时 this->rp依然为NULL,所以不能执行 --count操作,要对指针是否为NULL进行判断。 当然这些操作都是为了能让智能指针加入Stl中作为元素使用而设定的。
2. vector.push_back(object). 实际上是调用类的复制构造函数。
以上是关于再谈智能指针的主要内容,如果未能解决你的问题,请参考以下文章
前辈说先学会了这些Python知识点,再谈学习人工智能机器学习