首页 > 编程语言 >C++(STL):05---智能指针之unique_ptr

C++(STL):05---智能指针之unique_ptr

时间:2022-11-01 14:34:42浏览次数:51  
标签:p1 05 STL C++ int new unique ptr 指针

一、unique_ptr类

  • 头文件:#include<memory>
  • 智能指针,是一个模板。创建智能指针时,必须提供指针所指的类型

与shared_ptr的不同之处:

  • shared_ptr所指向的对象可以有多个其他shared_ptr智能指针
  • 而unique_ptr所指向的对象只能有一个unique_ptr指针,也就是自己。当unique_ptr被销毁时,它所指向的对象也被销毁

 

二、unique_ptr类的初始化

  • unique_ptr指针需要绑定到一个new返回的指针上,并且不能直接将new的结果用赋值运算符“=”赋值给unique_ptr
  1. unique_ptr<double> p1;//正确
  2. unique_ptr<int> p2(new int(42));//正确
  3. unique_ptr<int> p3 = new int(42);//错误

三、unique_ptr之间不存在拷贝与赋值

  • 原因:因为unique_ptr所指向的对象只能有一个unique_ptr指针,也就是一个引用计数。因此unique_ptr不支持普通的拷贝和赋值操作
  1. unique_ptr<string> p1(new string("HelloWorld"));
  2. unique_ptr<string> p2(p1);//是错误
  3. unique_ptr<string> p3;
  4. p3 = p1;//错误

特殊情况:

  • 虽然两个unique_ptr不可以同时指向同一个内存对象,但是可以将一个即将销毁的unqie_ptr指针拷贝或赋值给另一个unqie_ptr
  • 函数的参数传递和返回值就是一个很好的例子
//因为在函数内部的unique_ptr指针随着作用域的结束会自动销毁,因此可以将其作为返回值,然后将内存传递给另一个unique_ptr指针管理
unique_ptr<int> clone(int p)
{
return unique_ptr<int>(new int(p));
}
/*unique_ptr<int> clone(int p)
{
unique_ptr<int> ret(new int(p));
return ret;
}*/
int main()
{
unique_ptr<int> p = clone(10);
cout <<*p << endl; //打印10
return 0;
}

四、release、reset函数的使用

  • 虽然unique_ptr之间不能拷贝与赋值。但是可以使用release和reset函数来将指针的所有权从一个(非const)unique_ptr转移给另一个unique

release函数

  • 将当前的unique_ptr指针所指的内存置为空,并且对这块内存的所有权消失
  • 返回值:返回当前unique_ptr所指的内存
  1. unique_ptr<string> p1(new string("Hello"));
  2. unique_ptr<string> p2(p1.release());//p1将自己所指的内存空间置空,并且返回该内存空间。之后对该内存空间的操作权消失,从而p2得到该内存的权限

注意事项:

  • 因为release函数会使unque_ptr指针与内存之间的关系。所以unique_ptr调用release函数之后必须将返回值传递给另一个unqiue_ptr,否则就会内存泄露
  1. unique_ptr<string> p1(new string("Hello"));
  2. p1.release();//错误,虽然p1断开了与内存的关系,但是没有另一个unqieu_ptr来接手这块内存,造成内存泄漏
  3. /*
  4. 改正:
  5. unique_ptr<string> p2(p1.release()); //将p1的原来内存交给另一个unique_ptr管理
  6. */

reset函数

  • 用来重置当前unqie_ptr指针。
  • 重置之后接手另一块内存或者一直处于空状态
unique_ptr<string> p1(new string("Hello"));
p1.reset();//将p1置空,不指向内存对象
unique_ptr<string> p1(new string("Hello"));
p1.reset(nullptr);//同上
unique_ptr<string> p1(new string("Hello"));
unique_ptr<string> p2(new string("World"));
p1.reset(p2.release());//p2置空之后,然后p1也置空,然后p1来接手p2所指向的内存

五、重置unique_ptr类删除器

  • 概念:与shared_ptr类相同,当unque_ptr终止自己时,默认情况下会调用默认析构函数来释放(delete)自己所指向的对象。但是我们也可以通过重载来指定unqie_ptr的删除器 

语法格式:

  • 与shared_ptr重载删除器不同,unique_ptr重载删除器会影响到unique_ptr类型以及如何构造(或reset)该类型的对象
  • 我们必须在unique_ptr指向类型之后提供删除器
  1. //p指向一个类型为objT的对象,并使用一个类型为delT的对象释放objT对象
  2. //它会调用一个名为fcn的delT类型对象
  3. unique_ptr<objT,delT> p(new objT,fcn);

演示案例:

  • 现在我们修改在shared_ptr中定义过的函数,在里面使用unique_ptr,来重载unique_ptr的删除器
  • shared_ptr类文章点击我们使用decltype来指明函数类型,在后面加一个*代表函数指针
void f(destination &d)
{
connection c=connec(&d);
unique_ptr<connection,decltype(end_connection)*> p(&c,end_connection);
...//使用这个连接
//当f函数退出或者异常退出,p都会调用end_connection函数
}

六、unique_ptr与动态数组的使用

  • 标准库提供了一个可以管理new分配的数组的unique_ptr版本
  1. unique_ptr<int[]> arr(new int[3]{ 1,2,3 }); //定义一个指向int型数组的智能指针对象
  2. unique_ptr<int[]> arr2(new int[3]);
  3. arr.release(); //自动调用delete[]销毁其指针

unique_ptr<int[]> arr= new int[3]{ 1,2,3 }; //错误

  • 动态数组的访问:unique_ptr操作数组,不提供点和箭头成员运算符,因为数组不是一个对象。但是可以通过下标运算符来访问操作数组
  1. unique_ptr<int[]> arr(new int[3]{ 1,2,3 });
  2. for (int i = 0; i < 3; ++i)
  3. arr[i] = i;


标签:p1,05,STL,C++,int,new,unique,ptr,指针
From: https://blog.51cto.com/u_14934686/5813641

相关文章

  • C++:31---对象引用和赋值
    一、对象移动概述C++11标准引入了“对象移动”的概念对象移动的特性是:可以移动而非拷贝对象在C++旧标准中,没有直接的方法移动对象。因此会有很多不必要的资源拷贝标准库容器......
  • C++:32---IO库
    一、IO库I0库类型和头文件头文件类型iostreamistream,wistream从流读取数据ostream,wostream向流写入数据iostream,wiostream读写流fstreamifstream,wifstream从文件读取数......
  • C++:20---类模板(template)
    一、类模板与模板类类模板:一个模板(是模板)模板类:调用类模板生成的类对象(是类实体),也称为类模板的实例化类模板的定义:与函数模板的定义是一样的template<typenameT>classBlo......
  • 【c&c++】 linux C之basename, dirname函数
    环境(centos6.10):$uname-r2.6.32-754.el6.x86_64函数定义:///usr/include/libgen.hexternchar*__xpg_basename(char*__path)__THROW;#definebasename......
  • node05_模块化以及module对象
     1.定义一个自定义模块   //当前这个文件,就是一个用户自定义模块console.log('加载了06这个模块')2.引入定义的自定义模块   //使用require()方法......
  • node04_05时钟web服务器
    1.创建clock文件夹,里面有index.hrml和对应的css文件  2.编写node代码//1.1导入http模块consthttp=require('http')//1.2导入fs模块constfs=require('fs')......
  • c++11新增容器 array
    array中数据存于栈中 ......
  • 【C++】【纯代码】获取电脑的mac地址
    boolGetMacAddress(CString&LanMAC){#defineMAX_ADAPTER_NAME_LENGTH256#de......
  • C++的第一个程序
    #include<iostream>usingnamespacestd;intmain(){ cout<<"helloworld"<<endl; system("pause"); return0;}菜鸡,第一次用C++敲代码,记录一下心得:代......
  • C++——KMP算法
    ......