智能指针的发展史:
先从RAII说起:
RAII(Resource Acquisition Is Initialization)
资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源
的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释
放。
auto_ptr:
- 实际上,为了正确地管理资源,人们进行了包括但不仅限于flag、count等尝试,但还是会被野指针或者没有所指向空间的支配权折磨得死去活来。
- 于是乎,能够进行管理权转移的auto_ptr出现了。
- 可谓是一举惊天地啊!
- 虽然auto_ptr出生就自带光环啊,但他后天不努力,资质颇为平庸的说。
- 其资质平庸具体来说有:不能共享所有权、auto_ptr不能指向数组 、auto_ptr不能作为容器的成员、不能通过赋值操作来初始化auto_ptr 、不能把auto_ptr放入容器等等等等。
auto_ptr的模拟实现:
template <class T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
{}
~AutoPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
AutoPtr(const AutoPtr<T>& s)
: _ptr(s._ptr)
{
s._ptr = NULL;
}
AutoPtr& operator= (AutoPtr<T>& s)
{
if (s._ptr != _ptr)
{
if (_ptr)
delete _ptr;
_ptr = s._ptr;
s._ptr = NULL;
}
return *this;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
private:
T* _ptr;
};
scoped_ptr的模拟实现:
template <class A>
class ScopedPtr
{
public:
ScopedPtr(A* ptr)
:_ptr(ptr)
{}
~ScopedPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
A* operator->()
{
return _ptr;
}
A& operator*()
{
return *_ptr;
}
private:
ScopedPtr(const ScopedPtr<A>&s);//禁止使用拷贝构造函数
ScopedPtr& operator=(ScopedPtr<A>& s);//禁止赋值构造
private:
A* _ptr;
};
shared_ptr
- 可以认为每个shared-ptr都有一个关联的计数器,通常称其为引用计数。
- 无论何时,每当拷贝一个shared-ptr之后,计数器都会递增。
- 而当我们给shared-ptr赋予一个新值或是shared-ptr被销毁时,计数器就会递减。
- 一旦一个shared-ptr离开其作用域时,计数器就会递减。
- 当shared-ptr的计数器变为0,它就会自动释放自己所管理的对象。
template<class B>
class SharedPtr
{
public:
SharedPtr(B* s)
:_ptr(s)
, _count(new int(1))
{}
~SharedPtr()
{
if (--(*_count) == 0)
{
delete _ptr;
_ptr = NULL;
delete _count;
_count = NULL;
}
}
SharedPtr(SharedPtr<B>& s)
:_ptr(s._ptr)
, _count(s._count)
{
(*_count)++;
}
SharedPtr<B>& operator=(ScopedPtr<B>& s)
{
if (_ptr != s._ptr)
{
if (--(*count) == 0)
{
delete _ptr;
_ptr == NULL;
delete _count;
_count == NULL;
}
_ptr(s._ptr);
_count(s._count);
(*count)++:
}
return *this;
}
B& operator*()
{
return *_ptr;
}
B* operator->()
{
return _ptr;
}
int GetCount()
{
return *_count;
}
B* GetPtr()const
{
return _ptr;
}
private:
int* _count;//引用计数
B* _ptr;
};
weak_ptr
- weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。
- 将一个weak_ptr绑定到一个shared_ptr上,不会改变shared_ptr的引用计数。
- 一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。
- 即使有weak_ptr指向对象,对象也还是会被释放。
class WeakPtr
{
public:
WeakPtr()
:_ptr(NULL)
{}
WeakPtr(WeakPtr<C>& s)
:_ptr(s._ptr)
{}
~WeakPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
C* operator->()
{
return _ptr;
}
C& operator*()
{
return *_ptr;
}
private:
C* _ptr;
};