在之前介绍了我们自己实现的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;
}