热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++2.0新特性(六)——<SmartPointer(智能指针)之shared_ptr>

SmartPointer(智能指针)指的是一类指针,并不是单一某一个指针,它能知道自己被引用的个数以至于在最后一个引用消失时销毁它指向的对象,本文主要介绍C++2.0提供的新东西一

  Smart Pointer(智能指针)指的是一类指针,并不是单一某一个指针,它能知道自己被引用的个数以至于在最后一个引用消失时销毁它指向的对象,本文主要介绍C++2.0提供的新东西


一、Smart Pointer分类

  C++2.0提供了两大类型的智能指针,该模块都被定义于头文件

    

 


 二、标准库提供的智能指针类

2.1 class shared_ptr

  提供了共享式拥有语义,也就是说当对个shared_ptr可以共享(或拥有)同一个对象,对象的最后一个拥有者有责任销毁对象,并清理与该对象相关的所有资源,也就是说它所指向的对象不再被需要时,自动释放(当超出作用域时,其析构函数被调用,在析构函数中,将其引用计数减1,如果引用计数的值变为0,则删除关联的原始指针,默认使用delete释放内存)与对象相关的资源。


2.2 shared_ptr使用

  可以像其他任何指针一样使用,可以赋值、拷贝、比较它们也可以使用*和->操作符访问所指向的内容

1 #include
2 #include
3 #include
4 #include
5 using namespace std;
6
7 int main()
8 {
9 // two shared pointers representing two persons by their name
10 shared_ptr pNico(new string("nico"));//shared_ptr pNico = make_shared("nico");
11 shared_ptr pJutta(new string("jutta"));//注意,直接这种形式的构造表示这个构造函数是explicit
12
13 // capitalize person names
14 (*pNico)[0] = 'N';
15 pJutta->replace(0, 1, "J");
16
17 // put them multiple times in a container
18 vector> whoMadeCoffee;//此处放进去的是指针的引用,不是指针的内容
19 whoMadeCoffee.push_back(pJutta);
20 whoMadeCoffee.push_back(pJutta);
21 whoMadeCoffee.push_back(pNico);
22 whoMadeCoffee.push_back(pJutta);
23 whoMadeCoffee.push_back(pNico);
24
25 // print all elements
26 for (auto ptr : whoMadeCoffee) {
27 cout <<*ptr <<" ";
28 }
29 cout <30
31 // overwrite a name again
32 *pNico = "Nicolai";
33
34 // print all elements again
35 for (auto ptr : whoMadeCoffee) {
36 cout <<*ptr <<" ";
37 }
38 cout <39
40 // print some internal data
41 cout <<"use_count: " <42 //use_count 返回第一个元素被引用的次数,容器里面的三个拷贝和自身,加起来为4
43 }

 


 2.2 shared_ptr自定义析构函数

  再上图例子中,如果我们想自己定义析构函数的规则,不想用string*默认的,那我们就需要在构造时增加一点改动:

传递一个lambda作为shared_ptr构造函数的第二实参,这样申明的方式当其最末一个拥有者被摧毁时,会调用这个lambda

1 shared_ptr pNico(new string("nico"), [](string* p) {
2 cout <<"delete" <<*p <3 delete p; });


 2.3 shared_ptr对于数组的使用

  一般我们使用shared_ptr的时候没有指定其析构函数,是因为shared_ptr有一个默认的析构函数,这个默认的析构函数调用的是delete函数,这就意味着shared_ptr拥有的是由new建立起来的单一对象时,default delete才能适用,但是当我们使用数组的时候(数组需要delete[]),这个默认的delete就不适用了,我们需要自己定义delete.

std::shared_ptr p(new int[10], [](int *p) {delete[] p; });

注意:shared_ptr不提供operator [];


2.4 shared_ptr析构策略

  当shared_ptr的最后一个声明周期结束后,如果清理工作不仅仅是删除内存,这时你必须明确给出自己的deleter,可以指定属于自己的析构策略。

  下例展示:当指向临时文件的的最后一个引用消失时,我们要删除这个文件

1 #include
2 #include // for ofstream
3 #include // for shared_ptr
4 #include // for remove()
5
6 class FileDeleter
7 {
8 private:
9 std::string filename;
10 public:
11 FileDeleter (const std::string& fn)
12 : filename(fn) {
      std::cout <<"constructor" <13 }
14 void operator () (std::ofstream* fp) {
       std::cout <<"delete" <15 delete fp; // close file
16 std::remove(filename.c_str()); // delete file 删除文件
17 }
18 };
19
20 int main()
21 {
22 // create and open temporary file:

//这里会创建一个shared_ptr指针,令他指向new新建的输出文件,FileDeleter将负责shared_ptr的最后一个拷贝失去此输出文件的所有权时进行一系列清理操作

23 std::shared_ptr fp(new std::ofstream("tmpfile.txt"),
24 FileDeleter("tmpfile.txt"));

//解释上一行的运行原理:首先new时会产生一个临时对象,FileDeleter("tmpfile.txt")也会产生一个临时对象,当析构时,会将new的临时对象传给FileDeleter,即调用()运算符

      std::cout <<"reset" <

      fp.reset();
      std::cout <<"reset end" <

25 //... 26 }

 



推荐阅读
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 本文介绍了一道经典的状态压缩题目——关灯问题2,并提供了解决该问题的算法思路。通过使用二进制表示灯的状态,并枚举所有可能的状态,可以求解出最少按按钮的次数,从而将所有灯关掉。本文还对状压和位运算进行了解释,并指出了该方法的适用性和局限性。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 总结一下C中string的操作,来自〈CPrimer〉第四版。1.string对象的定义和初始化:strings1;空串strings2(s1);将s2初始 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
author-avatar
372630243
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有