此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记使用。

1、智能指针shared_ptr

shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内部采用计数机制来实现。

当新的shared_ptr与对象关联时,引用计数增加1。

当shared_ptr超出作用域时,引用计数减1。当引用计数变为0时,则表示没有任何shared_ptr与对象关联,则释放该对象。

一、基本用法

shared_ptr的构造函数也是explicit,但是,没有删除拷贝构造函数和赋值函数。

1)初始化

方法一:

shared_ptr<AA> p0(new AA("zq"));     // 分配内存并初始化。

方法二:

shared_ptr<AA> p0 = make_shared<AA>("zq");  // C++11标准,效率更高。

shared_ptr<int> pp1=make_shared<int>();         // 数据类型为int。

shared_ptr<AA> pp2 = make_shared<AA>();       // 数据类型为AA,默认构造函数。

shared_ptr<AA> pp3 = make_shared<AA>("zq");  // 数据类型为AA,一个参数的构造函数。

shared_ptr<AA> pp4 = make_shared<AA>("zq",8); // 数据类型为AA,两个参数的构造函数。

方法三:

AA* p = new AA("zq");

shared_ptr<AA> p0(p);                  // 用已存在的地址初始化。

方法四:

shared_ptr<AA> p0(new AA("zq"));

shared_ptr<AA> p1(p0);                 // 用已存在的shared_ptr初始化,计数加1。

shared_ptr<AA> p1=p0;                 // 用已存在的shared_ptr初始化,计数加1。

2)使用方法

  1. 智能指针重载了*和->操作符,可以像使用指针一样使用shared_ptr。
  2. use_count()方法返回引用计数器的值。
  3. unique()方法,如果use_count()为1,返回true,否则返回false。
  4. shared_ptr支持赋值,左值的shared_ptr的计数器将减1,右值shared_ptr的计算器将加1。
  5. get()方法返回裸指针。
  6. 不要用同一个裸指针初始化多个shared_ptr。
  7. 不要用shared_ptr管理不是new分配的内存。

3)用于函数的参数

与unique_ptr的原理相同。

4)不支持指针的运算(+、-、++、--)

二、更多细节

1)将一个unique_ptr赋给另一个时,如果源unique_ptr是一个临时右值,编译器允许这样做;如果源unique_ptr将存在一段时间,编译器禁止这样做。一般用于函数的返回值。

1 ) shared_ptr允许这样做。

2)用nullptr给shared_ptr赋值将把计数减1,如果计数为0,将释放对象,空的shared_ptr==nullptr。

3)release()释放对原始指针的控制权,将unique_ptr置为空,返回裸指针。

3) shared_ptr 不存在释放的操作,控制权不是由一个人说了算的。

4)std::move()可以转移对原始指针的控制权。还可以将unique_ptr转移成shared_ptr。

5)reset()改变与资源的关联关系。

pp.reset();        // 解除与资源的关系,资源的引用计数减1。

pp. reset(new AA("bbb"));  // 解除与资源的关系,资源的引用计数减1。关联新资源。

6)swap()交换两个shared_ptr的控制权。

void swap(shared_ptr<T> &_Right);

7)shared_ptr也可象普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。

8)shared_ptr不是绝对安全,如果程序中调用exit()退出,全局的shared_ptr可以自动释放,但局部的shared_ptr无法释放。

9)shared_ptr提供了支持数组的具体化版本。

数组版本的shared_ptr,重载了操作符[],操作符[]返回的是引用,可以作为左值使用。

10)shared_ptr的线程安全性:

  1. shared_ptr的引用计数本身是线程安全(引用计数是原子操作)。
  2. 多个线程同时读同一个shared_ptr对象是线程安全的。
  3. 如果是多个线程对同一个shared_ptr对象进行读和写,则需要加锁。
  4. 多线程读写shared_ptr所指向的同一个对象,不管是相同的shared_ptr对象,还是不同的shared_ptr对象,都需要加锁保护。

11)如果unique_ptr能解决问题,就不要用shared_ptr。unique_ptr的效率更高,占用的资源更少。

示例1:

#include <iostream>
#include <memory>
using  namespace std;class AA
{
public:string m_name;AA() { cout << m_name << "调用构造函数AA()。\n"; }AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }
};int main()
{shared_ptr<AA> pa0(new AA("zqa"));     // 初始化资源zqa。shared_ptr<AA> pa1 = pa0;                       // 用已存在的shared_ptr拷贝构造,计数加1。shared_ptr<AA> pa2 = pa0;                       // 用已存在的shared_ptr拷贝构造,计数加1。cout << "pa0.use_count()=" << pa0.use_count() << endl;   // 值为3。shared_ptr<AA> pb0(new AA("zqb"));    // 初始化资源zqb。shared_ptr<AA> pb1 = pb0;                      // 用已存在的shared_ptr拷贝构造,计数加1。cout << "pb0.use_count()=" << pb0.use_count() << endl;   // 值为2。pb1 = pa1;      // 资源zqa的引用加1,资源zqb的引用减1。pb0 = pa1;      // 资源zqa的引用加1,资源zqb的引用成了0,将被释放。cout << "pa0.use_count()=" << pa0.use_count() << endl;   // 值为5。cout << "pb0.use_count()=" << pb0.use_count() << endl;   // 值为5。
}

2、智能指针的删除器

在默认情况下,智能指针过期的时候,用delete原始指针; 释放它管理的资源。

程序员可以自定义删除器,改变智能指针释放资源的行为。

删除器可以是全局函数、仿函数和Lambda表达式,形参为原始指针。

示例:

#include <iostream>
#include <memory>
using  namespace std;class AA
{
public:string m_name;AA() { cout << m_name << "调用构造函数AA()。\n"; }AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }
};void deletefunc(AA* a) {    // 删除器,普通函数。cout << "自定义删除器(全局函数)。\n";delete a;
}struct deleteclass               // 删除器,仿函数。
{void operator()(AA* a) {cout << "自定义删除器(仿函数)。\n";delete a;}
};auto deleterlamb = [](AA* a) {   // 删除器,Lambda表达式。cout << "自定义删除器(Lambda)。\n";delete a;
};int main()
{shared_ptr<AA> pa1(new AA("a"), deletefunc);//shared_ptr<AA> pa2(new AA("b"), deleteclass());//shared_ptr<AA> pa3(new AA("c"), deleterlamb);//unique_ptr<AA,decltype(deletefunc)*> pu1(new AA("1"), deletefunc);// unique_ptr<AA, void (*)(AA*)> pu0(new AA("1"), deletefunc);//unique_ptr<AA, deleteclass> pu2(new AA("2"), deleteclass());//unique_ptr<AA, decltype(deleterlamb)> pu3(new AA("3"), deleterlamb);
}

C++11新特性——智能指针之shared_ptr相关推荐

  1. C++11新特性——智能指针之unique_ptr

    此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记使用. unique_ptr独享它指向的对象,也就是说,同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁 ...

  2. shellmad-18_C++新特性 智能指针的简易实现及添加模板

    前面提到可以用引用计数 + 写时拷贝 融合在一起, 为我们的智能指针增加新的功能 代码增加了CRefCount类, 来专门对CStudent类的对象的使用情况做统计 类很简单, 构造的时候, 计数器赋 ...

  3. C++11 解决内存泄露问题的智能指针:shared_ptr、unique_ptr、weak_ptr

    我们经常听到内存泄漏,但是对这个抽象的概念一直没有什么理解,比如产生内存泄漏又将如何,我平时写程序从来不考虑这个等等.这篇的目的:第一,给大家实验实验内存泄露带来的问题,让大家直观感受内存泄露.第二, ...

  4. 【C++11新特性】 C++11智能指针之shared_ptr

    http://blog.csdn.net/Xiejingfa/article/details/50750037 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...

  5. 【C++11新特性】 C++11智能指针之weak_ptr

    http://blog.csdn.net/xiejingfa/article/details/50772571 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...

  6. c++11新特性_【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以 ...

  7. 【C++11新特性】 C++11智能指针之unique_ptr

    原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/article/details/50759210 在前面一篇文章中,我们了解了C++11中引入的智能指针之一shar ...

  8. this指针_c++11新特性之智能指针

    很多人谈到c++,说它特别难,可能有一部分就是因为c++的内存管理吧,不像java那样有虚拟机动态的管理内存,在程序运行过程中可能就会出现内存泄漏,然而这种问题其实都可以通过c++11引入的智能指针来 ...

  9. C++11新特性之智能指针

    智能指针的特性 智能指针可以自动释放不再使用的内存,能够有效的防止内存泄漏. 智能指针是一个对象,普通指针是一个变量. 智能指针是对普通指针的封装,其安全性要高于直接使用普通指针. 智能指针的分类 共 ...

最新文章

  1. Java IO 体系(三):Reader与Writer
  2. 解决MyBatis的报错 There is no getter for property named ‘*‘ in ‘class java.lang.String‘
  3. EPUB.js 解决图片裁剪问题(缩放问题)
  4. 内核中 subsys_initcall 以及初始化标号
  5. python为csv文件添加表头_python读csv文件时指定行为表头或无表头的方法
  6. 梯度为什么是函数增加最快的方向
  7. 使用Python爬虫自动爬取沪港通每日持股数据
  8. CISCO路由器交换机简介及Packet+Tracer使用说明
  9. C++输出流cout的执行顺序问题
  10. Windows多用户配置,不同用户不同访问权限
  11. 分享一个漂亮的后台 admin 前端模板
  12. CAD偏移曲线(com接口c#语言)
  13. 将两个实数矩阵合并为一个复数矩阵
  14. mac系统ionic开发ios app从安装到打包
  15. 题目目录:java练习题
  16. 大数据技术为什么那么火?
  17. 程序是如何运行的呢?
  18. 设置element ui table表格线条颜色以及设置圆角/解决element ui table设置圆角后线条不显示或显示模糊问题,亲测有效
  19. 脚踩云视频和企服两个风口,“百家云”值30亿吗?
  20. python自动发送邮件脚本

热门文章

  1. FCC“网络中立”评论区现垃圾留言 部分民众身份被盗用
  2. 网关与微服务的概念及在微服务架构中的作用详解
  3. Linux TTY Driver
  4. [新闻] 2012互联网趋势报告摘要
  5. 推荐几个比较实用的浏览器插件
  6. WeCode在线少儿编程 | 用Python编写地球公转运动程序,月亮地球太阳全部都在!
  7. Levenberg-Marquardt方法
  8. 如何在win7 中安装windows sdk 7.1
  9. 图像阈值分割matlab,图像阈值分割Matlab版 | 学步园
  10. C语言 汉诺塔(hanoi)