unique_ptr是一种定义在中的智能指针。
unique_ptr可以独占它所指向的对象,所以不能进行复制操作,只能进行移动操作。
unique_ptr和share_ptr类型的指针有很大的不同:
share_ptr允许多个指针指向同一个对象;二unique_ptr在某一时刻只能有一个指针指向一个对象。
unique_ptr对象中保存指向某个对象的指针,当它本身被删除或者离开其作用域是会自动释放其所指对象所占的资源。
unique_ptr源码仿写:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
namespace wwn
{
template<typename _Tp>
struct default_delete//删除器
{
void operator()(_Tp* ptr)const//函数调用的重载
{
delete ptr;
}
};
template<typename _Tp>
struct default_delete<_Tp[]>//模板的重载
{
void operator()(_Tp* ptr)const
{
delete[]ptr;
}
};
template<typename _Tp,typename _Dp=default_delete<_Tp> >
class unique_ptr
{
private:
_Tp* _Ptr;
//unique_ptr不具有拷贝函数和赋值函数
unique_ptr(const unique_ptr&) = delete;
unique_ptr operator=(const unique_ptr&) = delete;
public:
typedef _Tp element_type;
typedef _Tp* pointer;
typedef _Dp delete_type;
//返回用于析构被管理对象的删除器
delete_type get_deleter() { return delete_type(); }
public:
unique_ptr() :_Ptr(nullptr) {};
explicit unique_ptr(pointer p) :_Ptr(p) {}
unique_ptr(unique_ptr&& _u) :_Ptr(_u.release()) {}
unique_ptr& operator=(unique_ptr&& _u)
{
reset(_u.release());//_Ptr=_u.release.但是使用reset更安全
return *this;
}
~unique_ptr()
{
if (_Ptr != nullptr)
{
//delete _Ptr;
get_deleter()(_Ptr);
}
_Ptr = nullptr;
}
pointer get()const { return _Ptr; }
//解引用被管理对象的指针
_Tp& operator*()const { return *get(); }
pointer operator->()const { return get(); }
//检查是否有关联的被管理对象
operator bool()const
{
return _Ptr != nullptr;
}
//重置被管理对象
void reset(pointer p = nullptr)
{
get_deleter()(_Ptr);
_Ptr = p;
}
//返回一个指向被管理对象的指针,并释放所有权
pointer release()
{
pointer tmp = _Ptr;
_Ptr = nullptr;
return tmp;
}
void swap(unique_ptr& _u)
{
using std::swap;
swap(_Ptr, _u._Ptr);
}
};
//动态管理数组的版本
template<typename _Tp, typename _Dp >
class unique_ptr<_Tp[],_Dp>
{
private:
_Tp* _Ptr;
unique_ptr(const unique_ptr&) = delete;
unique_ptr operator=(const unique_ptr&) = delete;
public:
typedef _Tp element_type;
typedef _Tp* pointer;
typedef _Dp delete_type;
delete_type get_deleter() { return delete_type(); }
public:
unique_ptr() :_Ptr(nullptr) {};
explicit unique_ptr(pointer p) :_Ptr(p) {}
unique_ptr(unique_ptr&& _u) :_Ptr(_u.release()) {}
unique_ptr& operator=(unique_ptr&& _u)
{
reset(_u.release());//_Ptr=_u.release.但是使用reset更安全
return *this;
}
~unique_ptr()
{
if (_Ptr != nullptr)
{
//delete _Ptr;
get_deleter()(_Ptr);
}
_Ptr == nullptr;
}
pointer get()const { return _Ptr; }
_Tp& operator*()const { return *get(); }
pointer operator->()const { return get(); }
_Tp& operator[](size_t index)const
{
//return get()[index];
return _Ptr[index];
}
operator bool()const
{
return _Ptr != nullptr;
}
void reset(pointer p = nullptr)
{
get_deleter()(_Ptr);
_Ptr = p;
}
pointer release()
{
pointer tmp = _Ptr;
_Ptr = nullptr;
return tmp;
}
void swap(unique_ptr& _u)
{
using std::swap;
swap(_Ptr, _u._Ptr);
}
};
}
class Object
{
private:
int value;
Object(const Object&)=delete;
Object& operator=(const Object&) = delete;
public:
Object(int x = 0) :value(x) { cout << "creat Object : " << this << endl; };
~Object() { cout << "destory Object : " << this << endl; };
int& Value() { return value; }
const int& Value()const { return value; }
void Print() const { cout << value << endl; }
};
wwn::unique_ptr<Object> fun(int x)
{
wwn::unique_ptr<Object> obj(new Object(x));
return obj;
}
//关闭文件的操作
struct Del_File
{
void operator()(FILE* pf) const
{
fclose(pf);
}
};
int main()
{
//wwn::unique_ptr<int> pInt(new int(100));
//wwn::unique_ptr<Object> pObj(new Object(20));
//wwn::unique_ptr<Object[], wwn::default_delete<Object[]>> pObj1(new Object[10]);
//pObj1[0].Print();
//cout << *pInt << endl;
//pObj->Print();
//文件操作
wwn::unique_ptr<FILE,Del_File> pfile(fopen("D://wwn.txt", "w"));
fprintf(pfile.get(), "lkhhello");
//vector的操作
vector<std::unique_ptr<Object>> vecObj;
vecObj.push_back(unique_ptr<Object>(new Object(10)));
vecObj.push_back(unique_ptr<Object>(new Object(20)));
std::unique_ptr<Object> pa = std::move(vecObj.back());
vecObj.pop_back();
return 0;
}
1、如何创建unique_ptr
unique_ptr不像share_ptr一样拥有标准函数库make_share来创建一个share_ptr实例。要想创建一个unique_ptr,我们需要将一个new操作符返回的指针传递给unique_ptr的构造函数。
int main()
{
unique_ptr<int> pInt(new int(5));
cout << *pInt;
}
2、unique_ptr无法进行拷贝构造和赋值操作
3、unique_ptr可以进行移动构造和移动赋值操作
unique_ptr虽然没有支持普通的拷贝和赋值操作,但是却提供了一种移动机制来将指针的所有权转移给另外一个指针。通过使用std:move()函数。
int main()
{
vector<std::unique_ptr<Object>> vecObj;
vecObj.push_back(unique_ptr<Object>(new Object(10)));
vecObj.push_back(unique_ptr<Object>(new Object(20)));
std::unique_ptr<Object> pa = std::move(vecObj.back());//此时vecObj里面的最后一个元素20归pa指针
vecObj.pop_back();//所以此时需要将最后一个元素删除
}
4、可以返回unique_ptr
unique_ptr不支持拷贝操作,但是有一个例外:可以从函数中返回一个unique_ptr.
例如:
wwn::unique_ptr<Object> fun(int x)
{
wwn::unique_ptr<Object> obj(new Object(x));
return obj;
}
int main()
{
int x = 5;
wwn::unique_ptr<Object> pa = fun(x);
wwn::unique_ptr<Object> pb;
pb = fun(x);
pa->Print();
pb->Print();
return 0;
}
5、unique_ptr的使用场景
- 为动态申请的资源提供异常安全保证
如下在常规操作中,我们可能由于抛出异常或者提前退出,而没有执行delete语句。
void fun()
{
int *p=new int(5);
//.....(可能会抛出异常)
delete p;
}
当使用unique_ptr来管理动态内存,只要unique_ptr创建成功,其析构函数都会被调用。这样就可以确保该动态资源会被释放。
- 返回函数内动态申请资源的所有权
示例:
wwn::unique_ptr<Object> fun(int x)
{
wwn::unique_ptr<Object> obj(new Object(x));
return obj;
}
int main()
{
int x = 5;
wwn::unique_ptr<Object> pb;
pb = fun(x);
pb->Print();
return 0;
}
- 在容器中保存指针
int main()
{
vector<std::unique_ptr<Object>> vecObj;
vecObj.push_back(unique_ptr<Object>(new Object(10)));
vecObj.push_back(unique_ptr<Object>(new Object(20)));
std::unique_ptr<Object> pa = std::move(vecObj.back());
vecObj.pop_back();
}
- 管理动态数组
标准库提供了一个可以管理动态数组的unique_ptr版本
int main()
{
unique_ptr<int[]> p(new int[5]{1,2,3,4,5});
p[0]=0;//重载了operator[]
}