C++——智能指针 unique_ptr
unique_ptr的实现原理:简单粗暴的防拷贝
目录
一、使用C++11中的新用法unique_ptr
二、使用c++11模拟实现
三、使用c++98特性实现
四、模拟实现unique_ptr
五、发现问题
一、使用C++11中的新用法unique_ptr
由于限制了拷贝以及赋值
导致缺陷:unique_ptr管理的资源无法共享
void TestUniquePtr()
{unique_ptr<int> up1(new int(10));*up1 = 100;// unique_ptr<int> up2(up1); // 无法进行拷贝构造unique_ptr<int> up3;// up3 = up1; // 无法进行赋值运算符重载
}int main()
{TestUniquePtr();_CrtDumpMemoryLeaks();return 0;
}
二、使用c++11模拟实现
使用了 C++11 中 =delete 这个语法的特性
“尝试引用已经删除的函数”
class CopyBan
{
public:CopyBan(int c): _c(c){}// c++11 实现方式CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;
private:int _c;
};
三、使用c++98特性实现
将拷贝构造 以及 赋值运算符重载 只声明不定义
并且将其访问权限设置为 private
class CopyBan
{
public:CopyBan(int c): _c(c){}// c++98 实现方式
private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);int _c;
};
四、模拟实现unique_ptr
无法进行拷贝构造以及对象赋值
#include<iostream>namespace wei
{template<class T>class unique_ptr{public:// RAIIunique_ptr(T* ptr = nullptr): _ptr(ptr){ }~unique_ptr(){if (_ptr){delete _ptr;_ptr = nullptr;}}// 具有指针类似的行为T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get(){return _ptr;}// 禁止拷贝/*C++98 只声明不定义拷贝构造函数和赋值运算符重载函数,并将权限修改为privateprivate:unique_ptr(const unique_ptr<T>&);unique_ptr<T> operator=(const unique_ptr<T>&);*/C++11unique_ptr(const unique_ptr<T>&) = delete;unique_ptr<T> operator=(const unique_ptr<T>&) = delete;private:T* _ptr;};
}void TestUniquePtr()
{wei::unique_ptr<int> up1(new int(10));*up1 = 100;wei::unique_ptr<int> up2(up1); 拷贝报错wei::unique_ptr<int> up3(new int(10));up3 = up1; 赋值报错
}int main()
{TestUniquePtr();_CrtDumpMemoryLeaks();return 0;
}
五、发现问题
再析构的时候只能进行delete,但如果用malloc申请的空间,就无法进行释放,因为new和delete配套,malloc和free配套,如果有其他类型的空间更无法进行释放,例如FILE类型文件,fopen和fclose配套。
namespace bite
{template<class T>class DFDef{public:void operator()(T*& ptr){if (ptr){delete ptr;ptr = nullptr;}}};增加一个模版参数,默认使用DFDef的方法进行delete释放资源template<class T, class DF = DFDef<T>> class unique_ptr{public:// RAIIunique_ptr(T* ptr = nullptr): _ptr(ptr){}~unique_ptr(){if (_ptr){//delete _ptr;// 应该根据用户提供的资源方式去释放//DF df;//df.operator()(_ptr); 这几种方式均可以//df(_ptr);DF()(_ptr);}}// 具有指针类似的行为T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get(){return _ptr;}// 防拷贝// C++11unique_ptr(const unique_ptr<T>&) = delete;unique_ptr<T> operator=(const unique_ptr<T>&) = delete;private:T* _ptr;};
}template<class T>
class Free
{
public:void operator()(T*& ptr) 其他的几种重载调用{if (ptr){free(ptr);ptr = nullptr;}}
};class FClose
{
public:void operator()(FILE*& ptr){if (ptr){fclose(ptr);ptr = nullptr;}}
};template<class T>
class deleteArray
{
public:void operator()(T*& ptr){if (ptr){delete[] ptr;ptr = nullptr;}}
};#include <malloc.h>
void TestUniquePtr()
{bite::unique_ptr<int> up1(new int(10));*up1 = 100;bite::unique_ptr<int, Free<int>> up2((int*)malloc(sizeof(int)));bite::unique_ptr<FILE, FClose> up3(fopen("111.txt", "w"));// bite::unique_ptr<int> up4(new int[10]);// 注意:一般不会将连续的空间使用unique_ptr管理// 因为:STL中已经存在了vector
}// 缺陷:unique_ptr管理的资源无法共享
int main()
{TestUniquePtr();_CrtDumpMemoryLeaks();return 0;
}