智能指针就是一个智能的指针:有以下两个特点
- 管理指针指向对象的释放问题;
- 又能像指针一样使用。
所以可以用RAII(资源获取就是初始化)的方式设计一个指针的对象用它的析构函数来管理资源、避免内存泄露。
shared_ptr是一个智能指针,比起auto_ptr 、unique它更像一个智能指针。
下面看一下SharePtr的简单实现↓
template<class T,class Del>
class SharePtr
{
public:
SharePtr(T* ptr) //构造函数
: _ptr(ptr), _ref(new int(1))
{
cout << "SharePtr(T* ptr)" << endl;
}
SharePtr( SharePtr& sp) //拷贝构造函数
{
cout <<"SharePtr( SharePtr& sp)" << endl;
_ptr = sp._ptr;
_ref = sp._ref;
(*_ref)++;
}
~SharePtr() //析构函数
{
Release();
}
void Release()
{
if (--(*_ref) == 0)
{
delete _ref;
_del(_ptr);
}
}
T* operator->() //箭头操作符的重载
{
return _ptr;
}
T& operator*() //解引用操作符重载
{
return *_ptr;
}
SharePtr& operator=(SharePtr& sp) //赋值操作符的重载
{
if (_ptr != sp._ptr)
{
Release();
_ptr = sp._ptr;
_ref = sp._ref;
(*_ref)++;
}
return *this;
}
private:
T* _ptr;
int* _ref;
Del _del; //-----这是一个对象函数决定着析构时以什么方式释放申请的空间
};
上面是class SharePtr的内容;
下面是使用的对象函数↓
template <class T>
struct Delete
{
void operator()(T*ptr)
{
cout <<"delete"<< endl;
delete ptr;
}
};
template <class T>
struct DeleteArr
{
void operator()(T*ptr)
{
cout << "delete[]" << endl;
delete[] ptr;
}
};
template <class T>
struct Free
{
void operator()(T* ptr)
{
cout << "free" << endl;
free(ptr);
}
};
template <class T>
struct Close
{
void operator()(T* ptr)
{
cout << "close" << endl;
if (ptr != NULL)
{
fclose(ptr);
}
}
};
在析构时_del的类型决定了析构函数释放的方式
下面是测试代码
void test()
{
SharePtr<int,Delete<int>> p1(new int(10));
SharePtr<int,Delete<int>> p2(p1);
SharePtr<string, DeleteArr<string>> p3(new string[3]);
SharePtr<string, DeleteArr<string>> p4(p3);
SharePtr<string, DeleteArr<string>> p5(p4);
SharePtr<int, Delete<int>> p6(new int(20));
SharePtr<int, Free<int>> p7 = (int*)malloc(sizeof(int));
SharePtr<FILE,Close<FILE>> p8 = fopen("FILENAME", "r");
cout << *p1<<","<<*p2 << endl;
p2 = p6;
*p1 = 15;
cout << *p1 << "," << *p2 << endl;
}
测试结果:
以上是SharePtr的简单实现,利用了引用计数和对象函数,能够较为完善的管理申请的空间,怎么申请怎么释放。所以说SharePtr是一个很好用的只能指针。