share_ptr 智能指针,也被称为共享指针,用于管理可以由多个智能指针共同拥有的动态分配对象。特别是,类型 shared_ptr<T> 用于管理 T 类型对象的所有权。

类构造函数 shared_ptr<T>(T * ptr) 可用于创建共享指针,管理由裸指针 ptr 给定地址的对象。shared_ptr 类可以重载指针运算符 * 和 ->。以下示例创建了一个由共享指针管理的动态分配整数,然后即可通过该指针访问它:

  1. int main()
  2. {
  3. shared_ptr<int> p(new int);
  4. *p = 45;
  5. cout << *p + 1;
  6. return 0;
  7. }

该代码将打印值 46。

以下是另外一个示例。假设要管理以下类对象的共享所有权:

  1. class Person
  2. {
  3. string name;
  4. int age;
  5. public:
  6. string to_string()
  7. {
  8. return name + "" + to_string(age) + "\n";
  9. }
  10. //构造函数
  11. Person () { name = " ";age = 0;}
  12. Person(const strings name, int age)
  13. {
  14. this->name = name;
  15. this->age = age;
  16. }
  17. }

现在可以创建 2 个共享指针,每一个都可以管理不同的对象,就像下面这样;

shared_ptr<Person> p1(new Person());
shared_ptr<Person> p2 (new Person ("Maria Wu", 23));

或者,也可以写成以下形式:

shared_ptr<Person> p1 = shared_ptr<Person>(new Person ());
shared_ptr<Person> p2 = shared_ptr<Person>(new Person("Maria Wu", 23));

share_ptr组

假设已经设置了一个共享指针来管理由裸指针 rPtr 指向的对象:

T * rPtr = new T();
shared_ptr<T> sPtr1(rPtr);

此时,sPtr1 变成了一个拥有 rPtr 的共享指针组中的唯一成员。该组维护了一个引用计数,即属于该组的共享指针数量。这个"组"被称为控制块,它本身实际上就是动态分配对象,可以保持跟踪引用计数和指向被管理对象的裸指针。当引用计数降至 0 时,控制块负责删除被管理的对象。可以将共享指针视为指向控制块的指针,而将控制块视为指向被管理的对象。

现在,如果 sPtr1 被用于初始化其他的共享指针,如以下语句所示:

shared_ptr<T> sPtr2 = sPtr1;

则 sPtr2 将变成和 sPtr1 同组的成员,共享 rPtr 对象的所有权,并且该组的引用计数也会增加 1。如果在此之后,sPtr2 被赋给了其他共享指针的值:

sPtr2 = sPtr3;

则 sPtr2 将放弃 rPtr 的所有权,离开 sPtr1 的组,转而加入 sPtr3 的组。第一个组(sPtr1 所在的组)的引用计数将减去 1,而第二个组(sPtr3 所在的组)的引用计数则增加 1。

双重管理的危险

在使用 share_ptr 时,应该避免出现可能导致两个指针组管理相同对象的情况。例如,来看以下代码:

  1. T * rPtr = new T();
  2. shared_ptr<T> sPtr1(rPtr);
  3. shared_ptr<T> sPtr2(rPtr);

这两个共享指针指向两个不同的控制块,但控制块管理的却是相同的对象。如果第一个组的引用计数降至 0 并删除该对象,那么这将导致其他组的指针变成悬挂指针。为了避免出现这种问题,给定的裸指针应该最多只能初始化一个共享指针。

make_shared<T>()函数

再来看一下 share_ptr 创建语句:

shared_ptr<Person> p1(new Person());

该语句的执行涉及两个独立的内存分配:一个分配控制块,第二个则分配内存给被管理的 Person 对象。每个内存分配都会产生相当一部分开销,所以,更高效的做法是,分配一个足够大的内存块,以同时保存控制块和被管理的对象。

下面这个库函数就可以做到这一点:

make_shared<T>()

使用该函数即可将上述共享指针创建语句改写为以下形式:

shared_ptr<Person> p1 = make_shared<Person>();

该版本的 make_Shared 语句可以使用默认构造函数初始化被管理的对象。

还有一个版本的 make_shared 语句可以采用传递给非构造函数的形参。因此,以下面的语句为例:

shared_ptr<Person> p2 (new Person ("Maria Wu", 23));

该语句可以被改写为以下形式:

shared_ptr<Person> p2 = make_shared<Person>("Maria Wu", 23);

推荐使用 make_shared 函数方式创建共享指针。除了更高效之外,它还无须直接处理裸指针,因此也消除了双重管理的可能性。

shared_ptr 成员函数

表 1 列出了处理 share_ptr 时最用的成员函数。

表 1 shared_ptr成员函数
成员函数 描 述
T* get() 返回指向被管理对象的裸指针,如果没有被管理的对象,则返回空指针
void reset() 释放任何可能存在的被管理对象的所有权。调用的共享指针被置为空
void reset(T* ptr) 释放当前被管理的对象的所有权。获取由 ptr 指向的对象的所有权
long use_count() 返回引用相同的被管理对象的共享指针数量

除此之外,还可以通过测试共享指针的值,检查某个共享指针是否有被管理的对象, 示例如下:

shared_ptr<T> p =....;
if ( P )
{//被管理的对象
}
else
{//共享指针为空
}

指向数组的share_ptr

默认情况下,shared_ptr 使用 delete 销毁被管理的对象。与 unique_ptr 不同的是,不能编写以下形式的语句:

shared_ptr<T[ ] > sPtr; // 错误

不能使用以上语句指定被管理的对象类型为数组。有一种简单方法可以绕过这种限制,那就是使用指向 T 类型矢量的共享指针:

shared_ptr<vector<T>> sVecPtr;

当矢量被销毁时,其析构函数将运行并销毁所有的矢量元素。

share_ptr智能指针使用详解相关推荐

  1. c++智能指针用法详解

    随笔 - 209   文章 - 2   评论 - 174 c++ 智能指针用法详解 本文介绍c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_p ...

  2. c++ 智能指针_详解 C++ 11 中的智能指针

    C/C++ 语言最为人所诟病的特性之一就是存在内存泄露问题,因此后来的大多数语言都提供了内置内存分配与释放功能,有的甚至干脆对语言的使用者屏蔽了内存指针这一概念.这里不置贬褒,手动分配内存与手动释放内 ...

  3. 智能指针 unique_ptr 详解

    一.智能指针 1.什么是智能指针 简单地说,C++智能指针是包含重载运算符的类,其行为像常规指针,但智能指针能够及时.妥善地销毁动态分配的数据,并实现了明确的对象生命周期,因此更有价值. 2.常规指针 ...

  4. c++ 智能指针用法详解

    http://www.cnblogs.com/TenosDoIt/p/3456704.html 本文介绍c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, un ...

  5. 【C++】智能指针用法详解(非常实用)

    一.指针与智能指针的区别 1.指针 C 语言规定所有变量在使用前必须先定义,指定其类型,并按此分配内存单元.指针变量不同于整型变量和其他类型的变量,它是专门用来存放地址的,所以必须将它定义为" ...

  6. C++ 智能指针 unique_ptr 详解与示例

    unique_ptr 是 C++ 11 提供的用于防止内存泄漏的智能指针中的一种实现,独享被管理对象指针所有权的智能指针.unique_ptr对象包装一个原始指针,并负责其生命周期.当该对象被销毁时, ...

  7. 如何使用指向类的成员函数的指针(详解!)

    原文:如何使用指向类的成员函数的指针(详解!) 另外一篇英文参考:Member Function Pointers and the Fastest Possible C++ Delegates 我们首 ...

  8. Android 系统(252)---Android:BLE智能硬件开发详解

    Android:BLE智能硬件开发详解 目录 前言 BLE是个什么鬼 BLE中的角色分工 主要的关键词和概念  GATT(Generic Attribute Profile ) Characteris ...

  9. get方法报空指针_C++基础教程之指针拷贝详解

    C++基础教程之指针拷贝详解 指针是编程人员的梦魇,对C语言的开发者是如此,对C++的开发者也是如此.特别是在C++中,如果不注意处理类中的指针,非常容易出问题.如果朋友们不相信可以看看下面的代码: ...

最新文章

  1. 归纳工作中用到的Linux 命令
  2. OpenCV中CV_IS_MAT_CONT(src->type dst->type) 的含义
  3. 【数据平台】Pytorch库初识
  4. 阵元间隔为半波长的均匀分布16元线阵
  5. Python_Tips[1] - 利用 Python 的字典实现 Switch 功能
  6. 如何调用DLL (基于Visual C++6.0的DLL编程实现)
  7. mysql relay log时间_如何得到Slave应用relay-log的时间
  8. 保存工具条菜单有bug吗?
  9. 训练日志 2019.7.24
  10. CTD数据库(Comparative Toxicogenomics Database)介绍与使用
  11. 解决spring-data-jpa 级联添加时,主表放弃对外键维护时外键字段为null
  12. TGA文件转YUV文件
  13. vtt或srt字幕挂载
  14. 偏偏在面试的时候踏入一个大坑--360浏览器兼容模式
  15. Lorem在HTML的使用
  16. SPSS—回归—多元线性回归(转)
  17. 新手指南:互联网创业要准备什么?
  18. SQL 2005镜像操作证书认证(非域方式)
  19. AI人脸检测智能视频融合平台EasyCVR新增告警预案功能
  20. java 二叉树的最小深度详解

热门文章

  1. GIS在石油行业中的应用
  2. Oracle 数据精度错误-ORA-01438
  3. 计算几何常用算法[转]
  4. English Words(For Computer Science)
  5. html转换成pdf在线转换器,pdf转换成HTML转换器
  6. python连接teradata_使用Teradata模块将Python与Teradata连接
  7. 在虚拟机上安装Ubuntu
  8. 中国高校鄙视链指南!
  9. 数据孤岛下的新破局 Real Time DaaS:面向 AP+TP 业务的数据平台架构
  10. linux设置mac地址命令,[转载]Linux下修改MAC地址