RAII
(
Resource Acquisition Is Initialization
)是一种
利用对象生命周期来控制程序资源
(如内
存、文件句柄、网络连接、互斥量等等)的简单技术。
在对象构造时获取资源
,接着控制对资源的访问使之在对象的生命周期内始终保持有效,
最后在
对象析构的时候释放资源
。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做
法有两大好处:
不需要显式地释放资源。
采用这种方式,对象所需的资源在其生命期内始终保持有效
auto_ptr
的实现原理:管理权转移的思想,下面简化模拟实现了一份wen
::auto_ptr
来了解它的原
理
namespace wen
{
template<class T>
class auto_ptr
{
public:
auto_ptr(T* ptr = nullptr)
:_ptr(ptr)
{}
//auto_ptr(const auto_ptr<T>& ap)
auto_ptr(const auto_ptr<T>& ap)
:_ptr(ap._ptr)
{
//_ptr = ap._ptr;
ap._ptr = nullptr;
}
/*auto_ptr<T>& operator=(const auto_ptr<T> ap)
{
_ptr = ap._ptr;
ap._ptr = nullptr;
return *this;
}*/
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
~auto_ptr()
{
delete _ptr;
}
private:
T* _ptr;
};
}
要修改不可用const对象
一般不用c++98的auto_ptr
C++11中开始提供更靠谱的unique_ptr
unique_ptr的实现原理:简单粗暴的防拷贝
C++11
中开始提供更靠谱的并且支持拷贝的
shared_ptr
shared_ptr
的原理:是通过引用计数的方式来实现多个
shared_ptr
对象之间共享资源
shared_ptr是线程安全的,可通过加锁来实现对其维护的引用计数线程安全,但是其指向的资源不一定线程安全,因为资源是由定义的人来处理,shared_ptr管不着。
下边简单实现一个shared_ptr
template<class T>
class shared_ptr
{
public:
shared_ptr(T* ptr = nullptr)
:_ptr(ptr)
,_count(new int(1))
{
}
shared_ptr(const shared_ptr<T>& sp)
:_ptr(sp._ptr)
,_count(sp._count)
{
++(*_count);
}
shared_ptr& operator=(const shared_ptr<T>& sp)
{
if (this == &sp)
return *this;
if (--(*_count) == 0)
{
delete _ptr;
delete _count;
}
_ptr = sp._ptr;
_count = ++(*sp._count);
}
T* operator->()
{
return this;
}
T& operator*()
{
return *this;
}
~shared_ptr()
{
if (--(*_count) == 0)
{
delete _ptr;
delete _count;
}
}
private:
T* _ptr;
int* _count;
};
当然,shared_ptr也不是万能的,它会有循环引用问题,需要借助weak_ptr来解决。
没有析构,会有内存泄漏风险。如下图:
weak_ptr实现:
template<class T>
class weak_ptr
{
public:
weak_ptr()
:_ptr(nullptr)
{}
weak_ptr(const shared_ptr<T>& sp)
:_ptr(sp.get())
{}
weak_ptr<T>& operator=(shared_ptr<T> sp)
{
_ptr = sp.get();
return *this;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
~weak_ptr()
{
}
private:
T* _ptr;
};
把这里修改一下就OK,weak_ptr不是RAII智能指针,是为了解决shared_ptr的循环引用