CONTENTS
参考链接:
【 http://www.cplusplus.com/reference/memory/unique_ptr/ 】
unique_ptr和auto_ptr类似,使用还是比较方便的,而且可以自定义删除函数。
测试类:
class TestCls { public: string name; int x; TestCls(string _name):name(_name) { cout<<"TestCls "<<name.c_str()<<" Constructor Called\n"; } ~TestCls() { cout<<"TestCls "<<name.c_str()<<" Destructor Called\n"; } };
最简单的使用方法:
void testUniquePtrFunc() { cout<<"enter testUniquePtrFunc\n"; std::unique_ptr<TestCls> uniptr1(new TestCls("TEST")); cout<<"leave testUniquePtrFunc\n"; }
输出:
enter testUniquePtrFunc TestCls TEST Constructor Called leave testUniquePtrFunc TestCls TEST Destructor Called
赋值,复制等逻辑:
void testUniquePtrFunc() { cout<<"enter testUniquePtrFunc\n"; std::unique_ptr<TestCls> uniptr1(new TestCls("TEST")); cout<<"uniptr1.get():"<<uniptr1.get()<<endl; std::unique_ptr<TestCls> uniptr2(std::move(uniptr1)); cout<<"uniptr1.get():"<<uniptr1.get()<<endl; cout<<"uniptr2.get():"<<uniptr2.get()<<endl; cout<<"uniptr1:"<<uniptr1<<endl;//重载了bool操作符,可直接使用 std::unique_ptr<TestCls> uniptr3 = std::move(uniptr2); cout<<"uniptr2.get():"<<uniptr2.get()<<endl; cout<<"uniptr3.get():"<<uniptr3.get()<<endl; cout<<"leave testUniquePtrFunc\n"; }
输出:
enter testUniquePtrFunc TestCls TEST Constructor Called uniptr1.get():0044CBE8 uniptr1.get():00000000 uniptr2.get():0044CBE8 uniptr1:0 uniptr2.get():00000000 uniptr3.get():0044CBE8 leave testUniquePtrFunc TestCls TEST Destructor Called
常用函数:
void testUniquePtrFunc() { cout<<"enter testUniquePtrFunc\n"; TestCls *pTest = new TestCls("TEST"); pTest->x = 10; cout<<"x:"<<pTest->x<<endl; std::unique_ptr<TestCls> uniptr1(pTest); pTest = NULL;//交给unique_ptr了,就不需要自己在管理了,可以防止误删除 cout<<"x:"<<uniptr1->x<<endl;//可以直接调用参考类的共有方法或者变量。 cout<<"x:"<<uniptr1.get()->x<<endl;//可以通过get方法获取原指针。 TestCls &testCls = *uniptr1; testCls.x = 100;//可以通过*获取参考指针的引用。 cout<<"x:"<<testCls.x<<endl; //可以通过release方法重新拿回指针,这样就需要自己管理 pTest = uniptr1.release(); delete pTest; pTest = NULL; TestCls *pTestA = new TestCls("A"); TestCls *pTestB = new TestCls("B"); std::unique_ptr<TestCls> uniptr2(pTestA); //调用reset,会先释放掉原有引用(pTestA),然后再持有新的引用(pTestB) uniptr2.reset(pTestB); //释放掉本地引用 uniptr2.reset(); cout<<"leave testUniquePtrFunc\n"; }
输出:
enter testUniquePtrFunc TestCls TEST Constructor Called x:10 x:10 x:10 x:100 TestCls TEST Destructor Called TestCls A Constructor Called TestCls B Constructor Called TestCls A Destructor Called TestCls B Destructor Called leave testUniquePtrFunc
自定义删除函数:
我们首先看下unique_ptr的源码,部分源码如下:
template<class _Ty, class _Dx> // = default_delete<_Ty> class unique_ptr : private _Unique_ptr_base<_Ty, _Dx, is_empty<_Dx>::value || is_same<default_delete<_Ty>, _Dx>::value> { // non-copyable pointer to an object public: typedef unique_ptr<_Ty, _Dx> _Myt; typedef _Unique_ptr_base<_Ty, _Dx, is_empty<_Dx>::value || is_same<default_delete<_Ty>, _Dx>::value> _Mybase; typedef typename _Mybase::pointer pointer; typedef _Ty element_type; typedef _Dx deleter_type; 。。。。 }
这里可以知道删除函数默认为default_delete<_Ty>,然后我们可以看下default_delete<_Ty>的实现,如下,有两个,一个是单个元素,一个是数组形式的:
// TEMPLATE CLASS default_delete template<class _Ty> struct default_delete { // default deleter for unique_ptr typedef default_delete<_Ty> _Myt; default_delete() _NOEXCEPT { // default construct } template<class _Ty2> default_delete(const default_delete<_Ty2>&, typename enable_if<is_convertible<_Ty2 *, _Ty *>::value, void>::type ** = 0) _NOEXCEPT { // construct from another default_delete } void operator()(_Ty *_Ptr) const _NOEXCEPT { // delete a pointer static_assert(0 < sizeof (_Ty), "can't delete an incomplete type"); delete _Ptr; } }; template<class _Ty> struct default_delete<_Ty[]> { // default deleter for unique_ptr to array of unknown size typedef default_delete<_Ty> _Myt; default_delete() _NOEXCEPT { // default construct } template<class _Other> void operator()(_Other *) const; // not defined void operator()(_Ty *_Ptr) const _NOEXCEPT { // delete a pointer static_assert(0 < sizeof (_Ty), "can't delete an incomplete type"); delete[] _Ptr; } };
这里我们实现一个最简单的删除函数,如下:
template<class _Ty> struct default_delete_custom { // default deleter for unique_ptr typedef default_delete_custom<_Ty> _Myt; default_delete_custom() _NOEXCEPT { // default construct } template<class _Ty2> default_delete_custom(const default_delete_custom<_Ty2>&, typename enable_if<is_convertible<_Ty2 *, _Ty *>::value, void>::type ** = 0) _NOEXCEPT { // construct from another default_delete } void operator()(_Ty *_Ptr) const _NOEXCEPT { // delete a pointer static_assert(0 < sizeof (_Ty), "can't delete an incomplete type"); delete _Ptr; cout<<"HI, I am default_delete_custom\n"; } };
然后调用:
void testUniquePtrFunc() { cout<<"enter testUniquePtrFunc\n"; TestCls *pTest = new TestCls("TEST"); std::unique_ptr<TestCls, default_delete_custom<TestCls>> uniptr1(pTest); pTest = NULL; uniptr1.reset(); cout<<"leave testUniquePtrFunc\n"; }
输出:
enter testUniquePtrFunc TestCls TEST Constructor Called TestCls TEST Destructor Called HI, I am default_delete_custom leave testUniquePtrFunc
源码学习:
比较多,随用随补吧。
发表评论