1.
RAII
资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。
2.
智能指针存在的理由
代码中经常会忘掉释放动态开辟的资源,容易造成资源的泄露,而智能指针可以自动化的管理指针所指向的动态资源的释放。
3.
智能指针
所谓智能指针就是智能/自动化的管理指针所指向的动态资源的释放。
每一种智能指针必须重载operator*()、operator->()。
1)
auto_ptr //STL
管理权转移
原则:永远只有一个对象在管理着一块空间。
template <class T> //模拟实现auto_ptr
class AutoPtr
{
public:
AutoPtr(T* ptr) //构造函数
:_ptr(_ptr)
{}
AutoPtr(AutoPtr<T>& ap) //拷贝构造
:_ptr(ap._ptr)
{
ap._ptr = NULL;
}
AutoPtr<T>& operator(AutoPtr<T>& ap) //赋值运算符重载
{
if(this != &ap)
{
delete _ptr;
_ptr = ap._ptr;
ap._ptr = NULL;
}
return *this;
}
~AutoPtr() //构造函数
{
delete _ptr;
}
T& operator*() //重载operator*
{
return *_ptr;
}
T* operator->() //重载operator->
{
return _ptr;
}
protected:
T* _ptr;
}
2)
scoped_ptr //Boost库
防拷贝
原则:只声明拷贝构造、赋值运算符重载且声明为私有的/受保护的。
template <class T> //模拟实现scoped_ptr
class ScopedPtr
{
public:
ScopedPtr(T* ptr) //构造函数
:_ptr(_ptr)
{}
~ScopedPtr() //构造函数
{
delete _ptr;
}
T& operator*() //重载operator*
{
return *_ptr;
}
T* operator->() //重载operator->
{
return _ptr;
}
T* GetPtr()
{
return _ptr;
}
protected:
ScopedPtr(const ScopedPtr<T>& sp); //拷贝构造
ScopedPtr<T>& operator=(const ScopedPtr<T>& sp); //赋值运算符重载
protected:
T* _ptr;
}
3)
unique_ptr //Boost库
防拷贝
4)
shared_ptr //Boost库
引用计数
实现了引用计数,只有当它所指向的最后一个对象被销毁时,指针才会被删除。
template <class T> //模拟实现shared_ptr
class SharedPtr
{
public:
SharedPtr(T* ptr) //构造函数
:_ptr(ptr)
,_refCount(new int(1))
{}
SharedPtr(SharedPtr<T>& sp) //拷贝构造
:_ptr(sp._ptr)
,_refCount(sp._refCount)
{
++(*_refCount);
}
SharedPtr<T>& operator=(SharedPtr<T>& sp) //赋值运算符重载 SharedPtr<T>& operator=(SharedPtr<T>& sp) //现代写法
{ {
if(this != &sp) swap(_ptr, sp._ptr);
{ swap(_refCount, sp._refCount);
Release(); return *this;
_ptr = sp._ptr; }
_refCount = sp._refCount;
++(*_refCount);
}
return *this;
}
~SharedPtr() //析构函数
{
Release();
}
void Release()
{
if(--(*_refCount)== 0)
{
delete _ptr;
delete _refCount ;
}
}
T& operator*() //重载operator*
{
return *_ptr;
}
T* operator->() //重载operator->
{
return _ptr;
}
protected:
T* _ptr;
int* _refCount; //引用计数
}
5)
weak_ptr //Boost库
目的:解决循环引用的问题。
不增加引用计数。
6)
scoped_array、shared_array
指针指向的是数组,与scoped_ptr、shared_ptr基本类似。但析构函数调用的是delete[],重载的是operator[]。
4.
定制删除器
在智能指针类的内部设置一个仿函数,仿函数默认为delete *ptr。
5.
循环引用
造成内存泄露。
使用一个弱引用智能指针weak_ptr智能指针来打破循环引用(weak_ptr不增加引用计数)。
struct ListNode
{
shared_ptr<ListNode> _prev; //造成循环引用问题
shared_ptr<ListNode> _next;
//weak_ptr<ListNode> _prev; //解决循环引用问题
//weak_ptr<ListNode> _prev;
};
void Test()
{
shared_ptr<ListNode> Node1;
shared_ptr<ListNode> Node2;
Node1->_next = Node2;
Node2->_prev = Node1;
};