· RAII(Resource Acquisition Is Initialization):
资源分配即初始化,定义一个类来封装资源的分配和释放, 在构造函数完成的资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。RAII要求,资源的有效期与持有资源的对象的生命期严格绑定,即有对象的构造函数完成资源的分配(获取),同时由析构函数完成资源的释放在这种要求下,只要对象能正确的析构,就不会出现资源泄露的问题。
· 为什么要有只能指针?
因为在代码中经常会忘掉释放动态开辟的资源,再碰到前面的逻辑处理时,也常常是如履薄冰小心谨慎,尽管如此还是会一不小心就泄漏了,防不胜防。
· 智能指针
所谓智能指针就是智能/自动化的管理指针所指向的动态资源的释放。
· 常用的智能指针
1.auto_ptr(管理转移)
#pragma once
template<class T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
{}
~AutoPtr()
{
if (_ptr)
{
printf("delete:0x%p\n",_ptr);
delete _ptr;
}
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
//ap2(ap1)
AutoPtr(AutoPtr<T>& ap)
:_ptr(ap._ptr)
{
ap._ptr = NULL;
}
//ap2 = ap3
AutoPtr<T>& operator=(AutoPtr<T>& ap)
{
if (this != &ap)
{
if (_ptr)
{
printf("delete:0x%p\n", _ptr);
delete _ptr;
}
_ptr = ap._ptr;
ap._ptr = NULL;
}
return *this;
}
private:
T* _ptr;
};
void TestAutoPtr()
{
int* p = new int(10);
AutoPtr<int> ap1(p);
AutoPtr<int> ap2(ap1);
AutoPtr<int> ap3(ap2);
AutoPtr<int> ap4(new int(20));
ap3 = ap4;
}
2.scoped_ptr(防拷贝)
template<class T>
class ScopedPtr
{
public:
ScopedPtr(T* ptr)
:_ptr(ptr)
{}
~ScopedPtr()
{
if (_ptr)
{
printf("delete:0x%p\n",_ptr);
delete _ptr;
}
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
// 防拷贝
// 1.只声明不实现
// 2.声明成私有保护
private:
ScopedPtr(const ScopedPtr<T>&);
ScopedPtr<T>& operator=(const ScopedPtr<T>&);
private:
T* _ptr;
};
void TestScopedPtr()
{
ScopedPtr<int> sp1(new int(10));
//ScopedPtr<int> sp2(sp1);
}
3.shared_ptr(引用计数)
template<class T>
class SharedPtr
{
public:
SharedPtr(T* ptr = NULL)
:_ptr(ptr)
,_refCount(new int(1))
{}
void Release()
{
if (--(*_refCount) == 0)
{
if (_ptr)
{
printf("delete: 0x%p\n", _ptr);
//delete _ptr;
_del(_ptr);
}
delete _refCount;
}
}
~SharedPtr()
{
Release();
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
// sp2(sp1)
SharedPtr(const SharedPtr<T>& sp)
:_ptr(sp._ptr)
,_refCount(sp._refCount)
{
++(*_refCount);
}
// sp2 = sp3
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
if (_ptr != sp._ptr)
{
Release();
_ptr = sp._ptr;
_refCount = sp._refCount;
++(*_refCount);
}
return *this;
}
private:
T* _ptr;
int* _refCount;
};
4.weak_ptr(采用引用计数,但会出现循环引用的问题)
template<class T>
class WeakPtr
{
public:
WeakPtr()
:_ptr(NULL)
{}
WeakPtr(const SharedPtr<T>& sp)
:_ptr(sp._ptr)
{}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
private:
T* _ptr;
};
struct ListNode
{
WeakPtr<ListNode> _prev;
WeakPtr<ListNode> _next;
/*SharedPtr<ListNode>_next;
SharedPtr<ListNode>_prev;*/
};
void TestCycleRef()
{
// 循环引用
WeakPtr<ListNode> cur = new ListNode;
WeakPtr<ListNode> next = new ListNode;
cur->_next = next;
next->_prev = cur;
}
· 如何解决循环引用的问题(定制删除器)
struct Deleter
{
template<class T>
void operator()(T* ptr)
{
delete ptr;
}
};
template<class T>
class WeakPtr;
template<class T, class D = Deleter>
class SharedPtr
{
friend class WeakPtr<T>;
public:
SharedPtr(T* ptr = NULL, D del = Deleter())
:_ptr(ptr)
,_refCount(new int(1))
,_del(del)
{}
void Release()
{
if (--(*_refCount) == 0)
{
if (_ptr)
{
printf("delete: 0x%p\n", _ptr);
//delete _ptr;
_del(_ptr);
}
delete _refCount;
}
}
~SharedPtr()
{
Release();
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
// sp2(sp1)
SharedPtr(const SharedPtr<T, D>& sp)
:_ptr(sp._ptr)
,_refCount(sp._refCount)
{
++(*_refCount);
}
// sp2 = sp3
SharedPtr<T, D>& operator=(const SharedPtr<T, D>& sp)
{
if (_ptr != sp._ptr)
{
Release();
_ptr = sp._ptr;
_refCount = sp._refCount;
++(*_refCount);
}
return *this;
}
protected:
T* _ptr;
int* _refCount;
D _del;
};