-
本文抄袭
-
RAll
- RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。
- 在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
- 不需要显式地释放资源。
- 采用这种方式,对象所需的资源在其生命期内始终保持有效。
-
智能指针概念
- 智能指针本质就是一个类模板,它可以创建任意的类型的指针对象,当智能指针对象使用完后,对象就会自动调用析构函数去释放该指针所指向的空间。
-
shared_ptr使用注意
- 不要把一个原生指针给多个shared_ptr管理;
- 不要把this指针给shared_ptr;
- 不要在函数实参里创建shared_ptr;
- 不要不加思考地把指针替换为shared_ptr来防止内存泄漏,shared_ptr并不是万能的,而且使用它们的话也是需要一定的开销的;
- 环状的链式结构shared_ptr将会导致内存泄漏(可以结合weak_ptr来解决);
- 共享拥有权的对象一般比限定作用域的对象生存更久,从而将导致更高的平均资源使用时间;
- 在多线程环境中使用共享指针的代价非常大,这是因为你需要避免关于引用计数的数据竞争;
- 共享对象的析构器不会在预期的时间执行;
- 不使用相同的内置指针值初始化(或reset)多个智能指针;
- 不delete get()返回的指针;
- 不使用get()初始化或reset另一个智能指针;
- 如果使用get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了;
- 如果你使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器。
-
智能指针shared_ptr的应用场景
- 有多个使用者共同使用同一个对象,而这个对象没有一个明确的拥有者
- 某一个对象的复制操作很费时.
- 要把指针存入标准库容器.
- 当管理需要特殊清除方式的资源时,可以通过定制shared_ptr的删除器来实现.
-
共享指针实现
#include <mutex>
using namespace std;
template<class T>
class shared_ptr {
public:
shared_ptr(T* _ptr) :ptr(_ptr)
{
ptrcount = new int(1);
mt = new mutex;
}
void AddCount()
{
mt->lock();
(*ptrcount)++;
mt->unlock();
}
shared_ptr(shared_ptr<T>& sp)
:ptr(sp.ptr)
,ptrcount(sp.ptrcount)
,mt(sp.mt)
{
AddCount();
}
shared_ptr<T&> operator=(const shared_ptr<T>& sp)
{
if (sp.ptr ~= ptr)
{
Release();
ptr = sp.ptr;
ptrcount = sp.ptrcount;
mt = sp.mt;
AddCount();
}
return *this;
}
~shared_ptr()
{
Release();
}
int& use_count()
{
return *ptrcount;
}
void Release()
{
bool deleteflag = false;
mt->lock();
if (--(*ptrcount) == 0)
{
delete ptrcount;
delete ptr;
ptrcount = nullptr;
ptr = nullptr;
deleteflag = true;
}
mt->unlock();
if (deleteflag == true)
{
delete mt;
mt = nullptr;
}
}
T& operator*()
{
return *ptr;
}
T* operator->() {
return ptr;
}
private:
T* ptr;
int* ptrcount;
mutex* mt;
};