this指针_c++11新特性之智能指针
很多人谈到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新特性之智能指针相关推荐
- C++11新特性之智能指针
智能指针的特性 智能指针可以自动释放不再使用的内存,能够有效的防止内存泄漏. 智能指针是一个对象,普通指针是一个变量. 智能指针是对普通指针的封装,其安全性要高于直接使用普通指针. 智能指针的分类 共 ...
- c++11新特性_c++11新特性(四)
4.lambda.bind.function 4.1.直接lambda表达式 lamda表达式不仅仅是一个语法新特性,对于没有用过java或C#lamda表达式读者,C++11的lamda表达式在一定 ...
- PotgreSQL 11 新特性之智能分区连接/聚合
文章目录 智能分区连接 智能分区聚合 PostgreSQL 11 提供了两个分区级别的新功能: 智能分区连接(partition-wise join),对于两个分区方式相同的分区表,如果使用分区键进行 ...
- 正则表达式提取器_C++11新特性7 - 正则表达式
C++11 新增了正则表达式的标准库支持,本文简介 C++ 正则表达式的使用 在 C++ 中使用正则表达式,和其它语言差别不大 int main() {regex e("abc*" ...
- 深入浅出之C++11新特性
1. auto类型赋予新含义 1.1 auto类型定义 在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的.auto 表示变量是自动存储的,这也是编译 ...
- COSMIC的后端学习之路——2.1 C++11新特性(1)
2.1 C++11新特性(1) 知识树 1.智能指针 (1)std::shared_ptr:共享的智能指针 ①初始化 ②获取原始指针 ③指定删除器(自定义删除对象) ④一些错误用法 (2)std::u ...
- 【C++11新特性】 C++11智能指针之weak_ptr
http://blog.csdn.net/xiejingfa/article/details/50772571 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...
- c++11新特性_【C++11新特性】 C++11智能指针之weak_ptr
如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以 ...
- 【C++11新特性】 C++11智能指针之shared_ptr
http://blog.csdn.net/Xiejingfa/article/details/50750037 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...
最新文章
- 解决异常:“The last packet sent successfully to the server was 0 milliseconds ago. ”的办法
- 怎么使用Docker搭建PHP开发环境呢?
- vue 传递 对象 路由_vue中路由参数传递可能会遇到的坑
- android Frame-By-Frame Animations(一帧一帧地播放动画)的使用
- 搞定研发知识管理,你的企业就能跑快一步
- 计算机一级考试复习资料,全国计算机一级考试复习资料
- 一个通用的VB磁盘文件搜索引擎类
- zabbix 2.4.5 自定义key监控redis
- power bi数据分析_设置Power BI数据网关
- pythonstdin_Python读取stdin方法实例
- 国密PSAM卡与CPU(用户卡)操作过程 小结
- UE4 角色沿着样条线移动
- 双鱼林java_双鱼林Java代码生成器
- jQuery HTML5文件上传美化插件jQuery.filer
- python输出棱形及对称三角
- java毕业设计大学生创业众筹系统mybatis+源码+调试部署+系统+数据库+lw
- 以太坊之Windows DApp开发环境的搭建
- 柔性数组 C/C++/Java
- Android蓝牙开发—经典蓝牙详细开发流程
- 深度学习深度前馈网络_深度学习前馈网络中的讲义第4部分
热门文章
- SENet双塔模型:在推荐领域召回粗排的应用及其它
- Tableau 2020.3 发布!新增 写入外部数据库 与 预测建模 等功能,进一步增强扩展分析
- 用Tableau画延展条形图(Extended Bar Chart)
- 支持向量机SVM原理(一)
- mysql查询操作及正则表达式小结
- js title 单选框 获取_js简单获取表单中单选按钮值的方法
- sr锁存器 数电_随机存取存储器 RAM || SRAM || DRAM || 数电
- QTexe软件设置系统默认的图标
- https下 http的会被阻塞 This request has been blocked; the content must be served over HTTPS.
- 登录抓包逆向分析学习笔记