 unique_ptr)
智能指针(四) unique_ptr文章目录智能指针(四) unique_ptrunique_ptr 的初始化*unique_ptr不支持的操作*移动语义release()reset()不带参数带参数release和 reset 源码比较nullptr指向一个数组swap()unique_ptr 转换为 shared_ptrshared_pre 注意点unique_ptr 支持拷贝*指定删除器(和shared_ptr不同)*删除器决定对象类型作为容器元素存储在容器中*unique_ptr需要明确知道类型的析构函数*unique_ptr 的初始化unique_ptr的初始化(和shared_ptr的初始化相同)// todo 使用 new intvoidfunc(){unique_ptrintpi;if(pinullptr){coutpi is nullendl;}unique_ptrintpi2(newint);if(pi2){coutpi2 is 初始化edendl;}}// todo 使用 make_uniquevoidfunc2(){unique_ptrintpimake_uniqueint(100);autop2make_uniqueint(100);if(pip2){coutpi and p2 is 初始化edendl;}}unique_ptr不支持的操作独占式指针该智能指针不支持拷贝动作定义时初始化voidfunc(){autoimake_uniqueint(100);// auto i2(i); // INFO unique_ptr是独占式指针该智能指针不支持拷贝动作定义时初始化// unique_ptrint i2(i);// unique_ptrint i3 i ; // INFO 智能指针不支持 赋值动作}移动语义voidfunc(){unique_ptrintimake_uniqueint(100);// auto i2(i);//不允许autoi2std::move(i);// todo 可以转交 控制权if(nullptr!i2nullptri){couti指针置空i2指向i 原来所指向对象std::endl;}}release()release() 放对指针的控制权切断了智能指针和其所指向的对象之间的联系返回裸指针将该智能指针置空。返回的这个裸指针我们可以手工delete来释放也可以用来初始化另外一个智能指针(shared_ptr的get则不可以)release()并不释放内存仅仅只是将std::unique_ptr中的数据指针置空并抛出数据指针voidfunc(){unique_ptrintuimake_uniqueint(100);// 初始化 另一个 智能指针autoiui.release();if(nullptr!inullptrui){coutui指针置空i指向ui 原来所指向对象std::endl;}}voidfunc2(){unique_ptrintuimake_uniqueint(100);int*iui.release();deletei;// 返回的 裸指针可以主动deleteif(nullptrinullptrui){coutui 和 i 指针 指向空std::endl;}}reset()不带参数reset()不带参数情况释放智能指针所指向的对象并将智能指针置空。会释放内存voidfunc(){unique_ptrstringps1(newstring(I Love Chinal !));ps1.reset();if(ps1nullptr){coutpsl被置空endl;}}带参数带参数的情况释放智能指针所指向的对象并让该智能指针指向新对象voidfunc2(){unique_ptrstringps1(newstring(I Love Chinal !));unique_ptrstringps2(newstring(I Love Chinal too!));cout*ps2:: *ps2endl;ps1.reset(ps2.release());// todo 释放了 ps2 指针并让 ps1 指向 ps2 原先指向的内存cout*ps1:: *ps1endl;}release和 reset 源码比较另外在std::unique_ptr中有两个成员函数比较容易混淆即pointerrelease()noexcept{return_STDexchange(_Mypair._Myval2,nullptr);}voidreset(pointer _Ptrnullptr)noexcept{pointer _Old_STDexchange(_Mypair._Myval2,_Ptr);if(_Old){_Mypair._Get_first()(_Old);}}从上面的源码中可以看出release()并不释放内存仅仅只是将std::unique_ptr中的数据指针置空并抛出数据指针而reset(pointer _Ptr nullptr)会调用析构函数释放内存。nullptrnullptr() 释放智能带针所指向的对象并将智能指针置空*// 不演示指向一个数组voidfunc(){unique_ptrint[]ps1(newint[10]);// todo 数组这里要跟上[]for(autoi0;i10;i){ps1[i]i;}for(autoi0;i10;i){coutps1[i]ps1[i]endl;}}swap()交换智能指针指向的对象和shared_ptr相同// 不演示unique_ptr 转换为 shared_ptr如果unique]ptr为右值就可以将它赋值给shared_ptr因为shared ptr包含一个显式构造函数可用于将右值unqiue_ptr转换为shared ptrvoidfunc(){unique_ptrintuimake_uniqueint(100);shared_ptrintsi(std::move(ui));coutsi.get():: *siendl;}shared_pre 注意点unique_ptr 支持拷贝虽然unique ptr智能指针不能拷贝但是当这个unique_ptr将要被销毁是可以拷贝的。最常见用法就是从函数返回namespacedetail{unique_ptrintfunc(intnums){returnstd::unique_ptrint(newint(nums));}}autoidetail::func(150);couti: *iendl;指定删除器(和shared_ptr不同)格式unique_ptr指向的对象类型删除器函数类型智能指针变量名voidmydelter(string*pdel){coutmydelter is calledendl;deletepdel;pdelnullptr;};voidfunc(){usingTvoid(*)(string*);// unique_ptrstring ui (new string(mydelter)); //调用默认删除器unique_ptrstring,Tui(newstring(mydelter),mydelter);}删除器决定对象类型作为容器元素存储在容器中namespacedetail3{voidmydelter(string*pdel){coutdetail3::mydelter is calledendl;deletepdel;pdelnullptr;};intmydelter2(string*pdel){coutdetail3::mydelter2 is calledendl;deletepdel;pdelnullptr;return0;};voidfunc(){usingTvoid(*)(string*);usingT2int(*)(string*);unique_ptrstringui1(newstring(mydelter));// 调用默认删除器unique_ptrstring,Tui2(newstring(mydelter),mydelter);unique_ptrstring,T2ui3(newstring(mydelter),mydelter2);vectorunique_ptrstringvs;vs.push_back(std::move(ui1));// vs.push_back(ui2); //error// vs.push_back(ui3); //errorvectorunique_ptrstring,TvsT;// 自定义删除器的必须标明 自定义删除器函数类型vsT.push_back(std::move(ui2));// vsT.push_back(std::move(ui3)); // 删除器类型不同 void mydelter(string *pdel)和 int mydelter2(string *pdel)是不同对象所以不能放入容器中}}unique_ptr需要明确知道类型的析构函数namespacedetail4{classTC;// 不提供析构函数voidfunc(){// unique_ptrTC up; // error: invalid application of sizeof to incomplete type detail4::TCshared_ptrTCtc;// shared_ptr可以正常运行}}参见 shared_ptr和unique_ptr深入探秘需要明确知道类型的析构函数*namespacedetail4{classTC;// 不提供析构函数voidfunc(){// unique_ptrTC up; // error: invalid application of sizeof to incomplete type detail4::TCshared_ptrTCtc;// shared_ptr可以正常运行}}参见 shared_ptr和unique_ptr深入探秘