|
在c++中,程序员需要自己管理向操作系统申请的内存,每一次new都应该有对应的delete来释放,程序员也是人,难免会出现忘记对申请的内存做释放操作,这样就会造成内存泄漏,如果这个程序是个长期运行的后台程序,这样就会带来很大的隐患,程序不断向系统申请内存,但用完之后并未还给系统,如此反复,便会造成系统的内存耗尽。
为了避免这种情况的发生,聪明的程序员搞出了一个叫智能指针的东西,使用智能指针能帮我们在适当的时候自动帮我们释放申请的内存,用了它,你再也不用担心你的程序出现内容泄漏啦。智能指针的实现利用了对象在销毁时会自动调用其析构函数这一特性,在析构函数中去释放所申请的内存,其中还用到了一种叫做引用计数的思想,即用一个整形的变量来记录每一块申请的内存被引用的次数,当被引用的次数为零时,则说明整个程序已经不再使用这块内存,这个时候就可以释放了,引用计数这一思想在很多地方都有用到,就比如java,php等语言的内存管理就用到了引用计数。结合c++的面向对象特性对智能指针进行封装实现,代码我贴在下面,结合运行结果分析一下就会明白其实现的机制了。
#include<iostream>
#include<stdexcept>
using namespace std;
//#define TEST_SMARTPTR
class Stub
{
public:
Stub()
{
cout<<"Stub:Constructor"<<endl;
}
void print(){
cout<<"Stub:print"<<endl;
}
~Stub(){
cout<<"Stub:Destructor"<<endl;
}
};
template<typename T>
class SmartPtr
{
private:
T *ptr;
size_t *pUse;
void decrUse(){
if((--*pUse)==0){
delete ptr;
delete pUse;
}
}
public:
SmartPtr(T *p=0)
{
ptr=p;
pUse=new size_t;
*pUse=1;
cout<<"SmartPtr Constructor"<<endl;
}
SmartPtr(const SmartPtr &src)
{
ptr=src.ptr;
pUse=src.pUse;
++*pUse;
cout<<"SmartPtr Copy Constructor"<<endl;
}
size_t getRefNum()
{
return *pUse;
}
bool isNull()
{
return ptr==0?true:false;
}
SmartPtr &operator=(const SmartPtr &rhs)
{
//self-assigningisalsoright
++*rhs.pUse;
decrUse();
ptr=rhs.ptr;
pUse=rhs.pUse;
return*this;
}
T* operator->()
{
if(ptr)
return ptr;
throw std::runtime_error("accessthroughNULLpointer");
}
const T* operator->() const
{
if(ptr)
return ptr;
throw std::runtime_error("accessthroughNULLpointer");
}
T& operator*()
{
if(ptr)
return *ptr;
throw std::runtime_error("dereferenceofNULLpointer");
}
const T& operator*() const
{
if(ptr)
return *ptr;
throw std::runtime_error("dereferenceofNULLpointer");
}
~SmartPtr(){
std::cout<<"SmartPtr:Destructor"<<std::endl;//fortesting
decrUse();
}
};
int main()
{
try{
SmartPtr<Stub> t;
t->print();
}catch(const exception &err){
cout<<err.what()<<endl;
}
cout<<"-------------------"<<endl;
SmartPtr<Stub> t1(new Stub);
cout<<t1.getRefNum()<<endl;
SmartPtr<Stub> t2(t1);
cout<<t1.getRefNum()<<endl;
SmartPtr<Stub> t3(new Stub);
t3=t2;
cout<<t1.getRefNum()<<endl;
t1->print();
(*t3).print();
cout<<"-------------------"<<endl;
return 0;
}
下面是运行的结果:

另外,在c++11标准中智能指针已经作为标准库存在,不需要我们自己去实现了。 |