本文共 5052 字,大约阅读时间需要 16 分钟。
https://blog.csdn.net/nou_camp/article/details/70186721
在上一篇博客中提到了Auto_ptr(C++智能指针(一)),下面进行模拟实现Auto_ptr
采用类模板实现#includeusing 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;}
//cout << *ap1 << endl;//会使代码出错
这是test函数中的代码,执行这句代码,会使程序崩溃,这是因为ap1已经把它指向的空间交给了ap2去管理,所以ap1已经不具备访问原来自己所指向的空间的权限。所以对它进行解引用是非法的。 所以可以看清auto_ptr的本质是管理权的转移,即ap1将自己所指向的空间交给ap2来管理,析构也是由ap2来完成。由上面可知auto_ptr有严重缺陷,所以后来有人写了scopedptr,慢慢发展形成了第三方库。
scopedptr ->防拷贝,意思就是不能进行拷贝,简单地说是一种简单粗暴的方式。下面模拟实现scopedptr。采用模板类实现。templateclass 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;}
scopedptr中对拷贝构造函数和赋值运算符的重载函数只是进行了声明,并没有去定义这两个函数,而且声明为protected或者是private,这是防止别人在类外对这两个函数进行定义。防止拷贝,所以说scopedptr是一种简单粗暴的方式。
编写程序往往要用到拷贝,这样scopedptr就不能起到相应的作用,所以便有了shared_ptr。
shared_ptr->采用了引用计数,优点是功能强大,但是也有缺点,缺点是过于复杂,而且会引起循环引用。 下面模拟实现shared_ptr#includeusing 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;}