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

c++11引入了三种智能指针:

  • std::shared_ptr

  • std::weak_ptr

  • std::unique_ptr

shared_ptr

shared_ptr使用了引用计数,每一个shared_ptr的拷贝都指向相同的内存,每次拷贝都会触发引用计数+1,每次生命周期结束析构的时候引用计数-1,在最后一个shared_ptr析构的时候,内存才会释放。

使用方法如下:

struct ClassWrapper {    ClassWrapper() {        cout <"construct" <endl;        data = new int[10];    }    ~ClassWrapper() {        cout << "deconstruct" << endl;        if (data != nullptr) {            delete[] data;        }    }    void Print() {        cout <"print" <endl;    }    int* data;};void Func(std::shared_ptr ptr) {    ptr->Print();}int main() {    auto smart_ptr = std::make_shared();    auto ptr2 = smart_ptr; // 引用计数+1    ptr2->Print();    Func(smart_ptr); // 引用计数+1    smart_ptr->Print();    ClassWrapper *p = smart_ptr.get(); // 可以通过get获取裸指针    p->Print();    return 0;}

智能指针还可以自定义删除器,在引用计数为0的时候自动调用删除器来释放对象的内存,代码如下:

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

关于shared_ptr有几点需要注意:

• 不要用一个裸指针初始化多个shared_ptr,会出现double_free导致程序崩溃

• 通过shared_from_this()返回this指针,不要把this指针作为shared_ptr返回出来,因为this指针本质就是裸指针,通过this返回可能 会导致重复析构,不能把this指针交给智能指针管理。

class A {    shared_ptr GetSelf() {       return shared_from_this();       // return shared_ptr(this); 错误,会导致double free    }  };
  • 尽量使用make_shared,少用new。

  • 不要delete get()返回来的裸指针。

  • 不是new出来的空间要自定义删除器。

  • 要避免循环引用,循环引用导致内存永远不会被释放,造成内存泄漏。

using namespace std;struct A;struct B;struct A {   std::shared_ptr bptr;   ~A() {       cout << "A delete" << endl;  }};struct B {   std::shared_ptr aptr;   ~B() {       cout << "B delete" << endl;   }};int main() {   auto aaptr = std::make_shared();   auto bbptr = std::make_shared();   aaptr->bptr = bbptr;   bbptr->aptr = aaptr;   return 0;}

上面代码,产生了循环引用,导致aptr和bptr的引用计数为2,离开作用域后aptr和bptr的引用计数-1,但是永远不会为0,导致指针永远不会析构,产生了内存泄漏,如何解决这种问题呢,答案是使用weak_ptr。

weak_ptr

weak_ptr是用来监视shared_ptr的生命周期,它不管理shared_ptr内部的指针,它的拷贝的析构都不会影响引用计数,纯粹是作为一个旁观者监视shared_ptr中管理的资源是否存在,可以用来返回this指针和解决循环引用问题。

  • 作用1:返回this指针,上面介绍的shared_from_this()其实就是通过weak_ptr返回的this指针,这里参考我之前写的源码分析shared_ptr实现的文章,最后附上链接。

  • 作用2:解决循环引用问题。

struct A;struct B;struct A {   std::shared_ptr bptr;   ~A() {       cout << "A delete" << endl;   }   void Print() {       cout << "A" << endl;   }};struct B {   std::weak_ptr aptr; // 这里改成weak_ptr   ~B() {       cout << "B delete" << endl;   }   void PrintA() {       if (!aptr.expired()) { // 监视shared_ptr的生命周期           auto ptr = aptr.lock();           ptr->Print();      }   }};int main() {   auto aaptr = std::make_shared();   auto bbptr = std::make_shared();   aaptr->bptr = bbptr;   bbptr->aptr = aaptr;   bbptr->PrintA();   return 0;}输出:AA deleteB delete

unique_ptr

std::unique_ptr是一个独占型的智能指针,它不允许其它智能指针共享其内部指针,也不允许unique_ptr的拷贝和赋值。使用方法和shared_ptr类似,区别是不可以拷贝:

using namespace std;struct A {   ~A() {       cout << "A delete" << endl;   }   void Print() {       cout << "A" << endl;   }};int main() {   auto ptr = std::unique_ptr(new A);   auto tptr = std::make_unique(); // error, c++11还不行,需要c++14   std::unique_ptr tem = ptr; // error, unique_ptr不允许移动   ptr->Print();   return 0;}

unique_ptr也可以像shared_ptr一样自定义删除器,使用方法和shared_ptr相同。

关于c++11的智能指针的使用就介绍到这里,大家有问题可以点此留言 ,我会尽快回复~

参考资料

https://www.jianshu.com/p/b6ac02d406a0

https://juejin.im/post/5dcaa857e51d457f7675360b#heading-16

《深入应用c++11:代码优化与工程级应用》

源码分析shared_ptr实现之修订版

一文让你搞懂设计模式

RAII妙用之ScopeExit

深入浅出虚拟内存

深入浅出虚拟内存(二)绘制虚拟内存排布图

深入浅出虚拟内存(三)堆内存分配及malloc实现原理

RAII妙用之计算函数耗时

一文吃透C++11中auto和decltype知识点

this指针_c++11新特性之智能指针相关推荐

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

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

  2. c++11新特性_c++11新特性(四)

    4.lambda.bind.function 4.1.直接lambda表达式 lamda表达式不仅仅是一个语法新特性,对于没有用过java或C#lamda表达式读者,C++11的lamda表达式在一定 ...

  3. PotgreSQL 11 新特性之智能分区连接/聚合

    文章目录 智能分区连接 智能分区聚合 PostgreSQL 11 提供了两个分区级别的新功能: 智能分区连接(partition-wise join),对于两个分区方式相同的分区表,如果使用分区键进行 ...

  4. 正则表达式提取器_C++11新特性7 - 正则表达式

    C++11 新增了正则表达式的标准库支持,本文简介 C++ 正则表达式的使用 在 C++ 中使用正则表达式,和其它语言差别不大 int main() {regex e("abc*" ...

  5. 深入浅出之C++11新特性

    1. auto类型赋予新含义 1.1 auto类型定义 在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的.auto 表示变量是自动存储的,这也是编译 ...

  6. COSMIC的后端学习之路——2.1 C++11新特性(1)

    2.1 C++11新特性(1) 知识树 1.智能指针 (1)std::shared_ptr:共享的智能指针 ①初始化 ②获取原始指针 ③指定删除器(自定义删除对象) ④一些错误用法 (2)std::u ...

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

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

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

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

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

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

最新文章

  1. 解决异常:“The last packet sent successfully to the server was 0 milliseconds ago. ”的办法
  2. 怎么使用Docker搭建PHP开发环境呢?
  3. vue 传递 对象 路由_vue中路由参数传递可能会遇到的坑
  4. android Frame-By-Frame Animations(一帧一帧地播放动画)的使用
  5. 搞定研发知识管理,你的企业就能跑快一步
  6. 计算机一级考试复习资料,全国计算机一级考试复习资料
  7. 一个通用的VB磁盘文件搜索引擎类
  8. zabbix 2.4.5 自定义key监控redis
  9. power bi数据分析_设置Power BI数据网关
  10. pythonstdin_Python读取stdin方法实例
  11. 国密PSAM卡与CPU(用户卡)操作过程 小结
  12. UE4 角色沿着样条线移动
  13. 双鱼林java_双鱼林Java代码生成器
  14. jQuery HTML5文件上传美化插件jQuery.filer
  15. python输出棱形及对称三角
  16. java毕业设计大学生创业众筹系统mybatis+源码+调试部署+系统+数据库+lw
  17. 以太坊之Windows DApp开发环境的搭建
  18. 柔性数组 C/C++/Java
  19. Android蓝牙开发—经典蓝牙详细开发流程
  20. 深度学习深度前馈网络_深度学习前馈网络中的讲义第4部分

热门文章

  1. SENet双塔模型:在推荐领域召回粗排的应用及其它
  2. Tableau 2020.3 发布!新增 写入外部数据库 与 预测建模 等功能,进一步增强扩展分析
  3. 用Tableau画延展条形图(Extended Bar Chart)
  4. 支持向量机SVM原理(一)
  5. mysql查询操作及正则表达式小结
  6. js title 单选框 获取_js简单获取表单中单选按钮值的方法
  7. sr锁存器 数电_随机存取存储器 RAM || SRAM || DRAM || 数电
  8. QTexe软件设置系统默认的图标
  9. https下 http的会被阻塞 This request has been blocked; the content must be served over HTTPS.
  10. 登录抓包逆向分析学习笔记