智能指针最基本的概念是引用计数,也就是智能指针内部有一个计数器,记录了当前内存资源到底有多少指针在引用(可以访问这个资源),当新增加一个可以访问这个资源的引用时,计数器会加1,反之会减去1,当计数器为0时,智能指针会自动释放他所管理的资源。手动申请,自动释放,就是其智能的体现。
模拟auto_ptr
先看看库里的解释
auto_ptr
template<class T>
class auto_ptr {
public:
typedef T element_type;
explicit auto_ptr(T *p = 0) throw();
auto_ptr(const auto_ptr<T>& rhs) throw();
auto_ptr<T>& operator=(auto_ptr<T>& rhs) throw();
~auto_ptr();
T& operator*() const throw();
T *operator->() const throw();
T *get() const throw();
T *release() const throw();
};
The class describes an object that stores a pointer to an allocated object of type T
. The stored pointer must either be null or designate an object allocated by a new
expression. The object also stores an ownership indicator. An object constructed with a non-null pointer owns the pointer. It transfers ownership if its stored value is assigned to another object. The destructor for auto_ptr<T>
deletes the allocated object if it owns it. Hence, an object of class auto_ptr<T>
ensures that an allocated object is automatically deleted when control leaves a block, even via a thrown exception.
template<typename T>
class AutoPtr
{
public:
AutoPtr()
:_ptr(new int(1))
{}
~AutoPtr()
{
delete _ptr;
_ptr=NULL;
}
AutoPtr( AutoPtr<T>& ap)
{
_ptr=ap._ptr;
ap._ptr=NULL;
}
AutoPtr<T>& operator=(AutoPtr<T>& ap)
{
delete _ptr;
_ptr=ap._ptr;
ap._ptr=NULL;
return *this;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
private:
T* _ptr;
};
void AutoPtrTest()
{
AutoPtr<int> ap1;
*ap1=10;
AutoPtr<int> ap2(ap1);
AutoPtr<int> ap3=ap1;
cout<<*ap1<<endl;
cout<<*ap2<<endl;
cout<<*ap3<<endl;
}
模拟实现scoped_ptr
scoped_ptr智能指针与std::auto_ptr不同,因为它是不传递所有权的。事实上它明确禁止任何想要这样做的企图!
template<typename T>
class ScopePtr
{
public:
ScopePtr()
:_ptr(new int(1))
{}
~ScopePtr()
{
delete _ptr;
_ptr=NULL;
}
T& operator *()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
protected:
ScopePtr(const ScopePtr<T>& sp);
ScopePtr<T>& operator=(const ScopePtr<T>& sp);
private:
T* _ptr;
};
void ScopePtrTest()
{
ScopePtr<int> sp1;
*sp1=1;
cout<<*sp1<<endl;
}
template <typename T>
class SharedPtr {
public:
SharedPtr():
p(NULL)
, pCount(new int(1))
{ }
explicit SharedPtr(T *pt)
: p(pt)
, pCount(new int(1))
{ }
SharedPtr(const SharedPtr &sp)
: p(sp.p)
, pCount(sp.pCount)
{
if (pCount)
++*pCount;
}
SharedPtr& operator=(const SharedPtr&);
~SharedPtr();
T& operator*()
{
return *p;
}
const T& operator*() const
{
return *p;
}
private:
T *p;
int *pCount;
};
template <typename T>
SharedPtr<T>::~SharedPtr()
{
if (pCount && 0 == --*pCount)
{
delete p;
delete pCount;
}
}
void SharedPtrTest()
{
SharedPtr<int> sp1(new int(1));
SharedPtr<int> sp2(sp1);
SharedPtr<int> sp3=sp1;
cout<<*sp1<<endl;
cout<<*sp2<<endl;
cout<<*sp3<<endl;
cout<<sp1.pCount<<endl;
<pre name="code" class="cpp" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 24px;"> cout<<sp2.pCount<<endl;
cout<<sp3.pCount<<endl;
}
这里有一个你在标准库中找不到的—引用数智能指针。大部分人都应当有过使用智能指针的经历,并且已经有很多关于引用数的文章。最重要的一个细节是引用数是如何被执行的—插入,意思是说你将
引用计数
的功能添加给类,或者是非插入,意思是说你不这样做。Boost shared_ptr是非插入类型的,这个实现使用一个从堆中分配来的
引用计数
器。关于提供参数化策略使得对任何情况都极为适合的讨论很多了,但是最终讨论的结果是决定反对聚焦于可用性。可是不要指望讨论的结果能够结束。
shared_ptr完成了你所希望的工作:他负责在不使用实例时删除由它指向的对象(pointee),并且它可以自由的共享它指向的对象