不管cpp有多少被诟病的地方,但是RAII是一个很伟大的发明。可以说不懂RAII,连C++的门槛都还没入。 《cpp primer》在第12章的动态内存中讲解了很多智能指针的使用,参考着另外一本国内的《C++泛型》的教材书上的代码,记个笔记。
RAII
RAII(Resource Acquisition is Initialization)
就是把资源(内存,文件,socket)等等和一个对象的生命周期绑定起来,当对象的生命周期到的时候,自动释放资源,避免手动new/delete管理内存。
在CPP的实现中,是讲裸指针以及指针的操作封装成一个类,通过类的生命周期管理来控制资源的释放。下面列出最简单的一个管理资源的模版
template <typename T>
class My_ptr
{
private:
T *_ptr;
public:
My_ptr(T *p):_ptr(p)
{
std::cout<<"Wrapped"<<std::endl;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
~My_ptr()
{
std::cout<<"Released"<<std::endl;
delete _ptr;
}
};
它将裸指针封装起来,封装在一个类里,类销毁了,资源也就释放了。这样避免了手动delete的操作。
Shared_ptr
Shared_ptr
在最原始的封装上更进一步,加入了引用计数。先定义一个资源的拥有者Res_ptr
,它拥有资源和计数器,不对外暴露接口,定义一个友元类Shared_ptr
,它通过Res_ptr
访问资源,同时具有复制,拷贝构造函数来增加计数。
template <typename T> class Shared_ptr;
template <typename T> class Res_ptr;
template <typename T>
class Res_ptr
{
private:
T* res_ptr;
int count;
Res_ptr(T* p):res_ptr(p),count(1){}
~Res_ptr()
{
delete res_ptr;
std::cout<<"resource released"<<std::endl;
}
friend class Shared_ptr<T>;
};
template <typename T>
class Shared_ptr
{
private:
Res_ptr<T>* ptr;
public:
T& operator*()
{
return *(ptr->res_ptr);
}
T* operator->()
{
return ptr->res_ptr;
}
Shared_ptr(T* p):ptr(new Res_ptr<T>(p))
{
std::cout<<"Shared_ptr constructor"<<"\t"<<"count="<<ptr->count<<std::endl;
}
Shared_ptr(const Shared_ptr& sp):ptr(sp.ptr)
{
++ptr->count;
std::cout<<"Shared_ptr copy constructor"<<"\t"<<"count="<<ptr->count<<std::endl;
}
~Shared_ptr()
{
std::cout<<"Shared_ptr deconstructor"<<"\t"<<"count="<<ptr->count<<std::endl;
if(--ptr->count==0)
delete ptr;
}
};
template <typename T>
Shared_ptr<T> make_shared(T&& ts)
{
return Shared_ptr<T>(new T(std::forward<T>(ts)));
}
int main()
{
{
auto p1 = ptr::make_shared<int>(1);
*p1 = 200;
{
auto p2 = p1;
auto p3 = p1;
auto p4 = p1;
}
std::cout<<*p1<<std::endl;
}
return 0;
}
输出结果如下
Shared_ptr constructor count=1
Shared_ptr copy constructor count=2
Shared_ptr copy constructor count=3
Shared_ptr copy constructor count=4
Shared_ptr deconstructor count=4
Shared_ptr deconstructor count=3
Shared_ptr deconstructor count=2
200
Shared_ptr deconstructor count=1
resource released