在之前介绍了我们自己实现的ScopPtr和SharePtr,今天来看一下库里面的智能指针的实现
scoped_ptr,
share_ptr包含于第三方boost库中,而且还被大家广泛使用。
所以在新的标准C++11中引用了boost库中智能指针的用法,只是将其稍作修改
将scoped_ptr重新定义为unique_ptr ,在boost库中不仅实现了share_ptr和scoped_ptr,还实现的share_array和scoped_array用来管理多个对象资源的保存和释放
这里我们先来模拟boost库中实现一个scoped_array,代码如下:
#include <iostream> #include <stdio.h> #include <windows.h> #include <memory> using namespace std; template<class T> class ScopedArray { public: ScopedArray(T* ptr) :_ptr(ptr) {} ~ScopedArray() { delete[] _ptr;//释放时用delete[] } T & operator[](int pos)//重载了[] { return _ptr[pos]; } private: T * _ptr; ScopedArray(const ScopedArray<T> & p1); ScopedArray<T> &operator=(const ScopedArray<T> & p1); }; void test() { ScopedArray<int> p1(new int[10]); p1[0] = 1; p1[1] = 2; p1[2] = 3; cout << p1[0] << endl; cout << p1[1] << endl; cout << p1[2] << endl; } int main() { test(); system("pause"); return 0; }
现在来看C++11中的智能指针是用法:
#include <stdio.h> #include <windows.h> #include <memory> #include <string> #include <iostream> using namespace std; void test() { auto_ptr<int> ap1(new int(10)); cout << *ap1 << endl; unique_ptr<int> up1(new int(20)); cout << *up1 << endl; shared_ptr<int> sp1(new int(30)); cout << *sp1 << endl; /*auto_ptr<string> ap2(new string("hello world")); auto_ptr<string> ap3(ap2); cout << *ap3 << endl;//管理权转移的用法,下面的*ap2为解引用空指针 cout << *ap2 << endl;*/ //unique_ptr<string> up2(new string("somebody")); //unique_ptr<string> up3(up2);//编译不通过,下面是库里面的实现拷贝构造 ////unique_ptr(const _Myt&) = delete; ////_Myt& operator=(const _Myt&) = delete; } int main() { test(); system("pause"); return 0; }
因为标准库里没有实现array版本,其实是有另外一种解决方法的。
先介绍一个新的概念:仿函数(函数对象)对象像函数一样使用
struct Less { bool operator()(int a, int b)//重载了() { return a < b; } }; void test_1() { Less less;//感觉上像是实现了一个函数 cout << less(1, 2) << endl; }
因为智能智能管理的对象不一定是new出来的,有可能是new[],malloc ,fopen等等,所以要按其对用的方法正确是释放。例如:
//定制删除器 template<class T> struct DeleteArray { void operator()(T * ptr) { delete[] ptr; } }; void test_2() { DeleteArray<int> da; //ScopedArray<int> Sp1(new int[10]); int * p1 = new int[10]; da(p1);//相当于delete[] p1; }
C++11中的定制删除器就是用仿函数来实现的。
//实现一个普通的指针是释放。作为下面初始化时的缺省参数 template<class T> struct Delete { void operator()(T * ptr) { delete ptr; } }; //定制删除器 template<class T> struct DeleteArray { void operator()(T * ptr) { delete[] ptr; } }; //针对于文件的定制删除器 struct FClose { void operator()(FILE * fd) { fclose(fd); } }; template<class T,class DA=Delete<int>>//缺省的处理方法为普通指针的释放 class ScopedPtr { public: ScopedPtr(T* ptr, DA da) :_ptr(ptr), _da(da) {} ~ScopedPtr() { //delete _ptr;//释放时用delete _da(_ptr);//用定制删除器来实现释放 } T& operator*() { return *_ptr; } T * operator->() { return _ptr; } private: T * _ptr; DA _da; ScopedPtr(const ScopedPtr<T> & p1); ScopedPtr<T> &operator=(const ScopedPtr<T> & p1); }; void test_2() { DeleteArray<int> da; ScopedPtr<int, DeleteArray<int> > Sp1(new int[10], da); DeleteArray<string> da1; ScopedPtr<string, DeleteArray<string> > Sp2(new string[10], da1); ScopedPtr<FILE, FClose>Sp3(fopen("test.txt", "w"), FClose()); } int main() { test_2(); system("pause"); return 0; }
如果是库里面的话,我们是不用传第二个模板参数的。
//定制删除器 template<class T> struct DeleteArray { void operator()(T * ptr) { delete[] ptr; } }; //针对于文件的定制删除器 struct FClose { void operator()(FILE * fd) { fclose(fd); } }; template<class T, class DA = Delete<T>>//缺省的处理方法为普通指针的释放 class ScopedPtr { public: ScopedPtr(T* ptr, DA da) :_ptr(ptr), _da(da) {} ~ScopedPtr() { //delete _ptr;//释放时用delete _da(_ptr);//用定制删除器来实现释放 } T& operator*() { return *_ptr; } T * operator->() { return _ptr; } private: T * _ptr; DA _da; ScopedPtr(const ScopedPtr<T> & p1); ScopedPtr<T> &operator=(const ScopedPtr<T> & p1); }; void test_3() { shared_ptr<string> sp1(new string[10], DeleteArray<string>()); shared_ptr<string> sp2(new string, Delete<string>()); shared_ptr<FILE> sp3(fopen("test.txt", "w"), FClose()); } int main() { test_3(); system("pause"); return 0; }