智能指针主要解决被多个对象引用时,资源如何释放的问题。
下面介绍一下boost库中的shared_ptr和weak_ptr:
Shared_ptr:当进行拷贝和赋值操作时, shared_ptr所指向的对象的引用计数都会增加,一旦变为0,就会自动释放自己管理的对象。(shared_ptr所指向的对象有一个被释放时,引用计数就会减1)
Weak_ptr: weak_ptr是一种不控制所指向对象生存周期的智能指针,它指向一个shared_ptr管理的对象时,并不会改变对象的引用计数(引用计数不增加),一旦最后一个指向shared_ptr的对象被销毁,对象就会被释放,即使有weak_ptr指向该对象,还是会被释放。
当创建一个weak_ptr时,要用一个shared_ptr来初始化,由于对象可能不存在,我们不能使用weak_ptr来访问对象,通过调用lock()方法,检查对象是否存在,若存在,则返回一个指向共享对象的shared_ptr.
原理:在创建共享对象时,要使用强指针 shared_ptr,若将该对象给其他线程时,则需要将强指针 shared_ptr转化为弱指针weak_ptr
(强指针的引用计数会增加,不转化为弱指针则一旦被其他线程调用,则该对象将一直不能析构,weak_ptr对象引用资源不会增加引用计数)要是弱指针weak_ptr想访问该对象时,不能通过weak_ptr来直接访问资源,需要进行提升(shared_ptr能保证自己没被释放之前,所管理的资源是不会被释放的,当shared_ptr引用计数为0时,释放资源,即使有weak_ptr指向它,而weak_ptr通过lock()方法来判断所管理的资源是否被释放,访问时要进行提升)weak_ptr为shared_ptr,将该弱指针提升为强指针,若提升成功,指针不为空,否则为空。

重磅推荐《linux多线程服务器编程》—第一章1.6节 神器shared_ptr/weak_ptr 书目作者陈硕(很腻害的一个大神)
附上一个自己实现的智能指针,通过链表来存储这些被引用的资源,当我们在实现指针的拷贝,赋值,析构等操作时,资源引用计数会相应的增加和减少。会遍历链表找到该资源的类型,对该资源计数引用增加减少,若计数减少为0时,则释放该资源节点。
//智能指针
class HeapTable//给资源上的指针计数
{
public:
static HeapTable *Getinstance()//单例 不同类型实例化只能在同一个链表
{
static HeapTable mHeapTable;
return &mHeapTable;
}
~HeapTable()
{
Node *pcur=phead;
while (pcur != NULL)
{
phead=phead->mpnext;
delete pcur;
pcur=phead;
}
}
void addRef(void *ptr)
{
Node *pcur=phead->mpnext;
while (pcur != NULL)
{
if (pcur->paddr == ptr)//查找到对该资源计数器加1
{
pcur->mcount++;
return;
}
pcur=pcur->mpnext;
}
pcur=new Node;//没查找到 进行头插
pcur->mpnext=phead->mpnext;
phead->mpnext=pcur;
}
void delRef(void *ptr)
{
Node *pcur=phead->mpnext;
while (pcur != NULL)
{
if (pcur->paddr == ptr)//查找到对该资源计数器减1
{
pcur->mcount--;
return;
}
pcur=pcur->mpnext;
}
}
int GetRef(void *ptr)
{
Node *pcur=phead->mpnext;
while (pcur != NULL)
{
if (pcur->paddr == ptr)
{
return pcur->mcount;
}
pcur=pcur->mpnext;
}
return -;
}
private:
HeapTable(){phead = new Node;}
class Node
{
public:Node(void *ptr=NULL):mcount(),paddr(ptr),mpnext(NULL)
{
if (paddr != NULL)
{
mcount=;
}
}
int mcount;
void *paddr;//指向资源
Node *mpnext;
};
Node *phead;
};
template<typename T>
class CsmartPtr
{
public:
CsmartPtr(T* str = NULL):mpstr(str)//构造
{
if (mpstr != NULL)
{
addRef();
}
}
CsmartPtr(const CsmartPtr<T> &src):mpstr(src.mpstr)//拷贝构造
{
if (mpstr != NULL)
{
addRef();
}
}
CsmartPtr<T>& operator=(const CsmartPtr<T> &src)//赋值运算符重载
{
if (this == &src)//防止自赋值
{
return *this;
}
if (mpstr != NULL)//释放原来的空间
{
delRef();
if (GetRef() == )
{
delete mpstr;
mpstr=NULL;
}
}
mpstr=src.mpstr;
addRef();
return *this;
}
~CsmartPtr()
{
cout<<"this"<<this<<endl;
delRef();
if (GetRef() == )
{
delete mpstr;
mpstr=NULL;
}
}
T & operator *(){return *mpstr;}
const T & operator *()const{return *mpstr;}
T* operator ->(){return mpstr;}
const T * operator ->()const{return mpstr;}
void addRef(){ mpHeapTab->addRef(mpstr);}
void delRef(){ mpHeapTab->delRef(mpstr);}
int GetRef() {return mpHeapTab->GetRef(mpstr);}
private:
T *mpstr;
static HeapTable *mpHeapTab;//静态指针
};
//静态变量在全局进行初始化
template<typename T>
HeapTable*CsmartPtr<T>::mpHeapTab=HeapTable::Getinstance();
int main()
{
int *p = new int;
CsmartPtr<int>pointer1(new int);
CsmartPtr<int>pointer2(new int);
CsmartPtr<int>pointer3(pointer1);
pointer2=pointer1;
CsmartPtr<char> pointer4((char*)p);
return ;
}