ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C++(20)——智能指针

C++(20)——智能指针 1. 内存泄漏1.1 概念内存泄漏由于疏忽或错误而造成程序未能释放已经不再使用的内存失去了对该段内存的控制而造成内存的浪费危害长期运行的程序出现内存泄漏会导致响应越来越慢最终卡死1.2 分类1.2.1 堆内存泄漏堆内存是指程序执行种依据要分配通过malloc/new等从堆中分配的一块内存用完后必须通过调用相应的free或delete删掉如果这部分内存没有被释放那么这部分空间将无法再使用产生Heap Leak堆内存泄漏1.2.2 系统内存泄漏指的是程序使用系统分配的资源比方套接字、文件描述符、管道等没有对应的函数释放调导致系统资源的浪费1.3 如何避免1.事前预防型使用RAII思想或智能指针2. 事后差错型使用泄漏检测工具2. 智能指针2.1 RAIIRAIIresource acquisition is initialization是一种利用对象生命周期来控制资源如内存、文件句柄、网络链接的简单技术在对象构造时获取资源控制对资源访问使之在对象的生命周期内始终有效最后在对象析构的时候释放资源。把管理一份资源的责任托管给了一个对象。两个好处1. 不需要显式地释放资源 2. 对象所需的资源在其生命期内始终有效2.2 原理1. RAII特性2. 重载operator*和operator-具有像指针一样的行为2.3 std::auto_ptr文档介绍C98提供的独占智能指针C11中已废除C17中被移出标准库致命缺陷拷贝时会发生所有权转移极易产生野指针auto_ptrint p1(new int(10)); auto_ptrint p2 p1; //拷贝 // p1 被置空所有权转移到 p2 cout *p1; // ❌运行崩溃p1是空野指针2.4 std::unique_ptr文档介绍C11中提供的独占式智能指针特点1. 独占所以权一块堆内存同一时刻只能被一个 unique_ptr 管理2. 禁止拷贝构造、赋值重载不能复制3. 支持移动语义std::move转移资源的管理权4. 无引用计数开销很小unique_ptrint p1(new int(100)); // unique_ptrint p2 p1; // 拷贝编译报错禁止 unique_ptrint p3 move(p1); //移动所有权转移 //转移后 p1 变成空指针不再管理资源 cout *p3 endl;常用接口p.get(); // 返回裸指针 p.reset(); // 释放资源指针置空 p.release(); // 放弃管理权返回裸指针不释放内存2.5 std::shared_ptr文档介绍C11中提供的共享式智能指针特点1. 共享所以权多个 share_ptr 可以指向同一块堆内存2. 内部维护一块引用计数器记录当前有多少指针在管理这份资源。新增一个指针计数1销毁一个指针计数-1计数0时堆内存才释放3. 可以拷贝、赋值4. 引用计数有额外开销shared_ptrint sp1(new int(20)); shared_ptrint sp2 sp1; //拷贝计数1 cout sp1.use_count() endl; //查看引用计数输出2致命缺陷循环引用内存泄漏struct Node { shared_ptrNode _next; shared_ptrNode _prev; }; int main() { shared_ptrNode n1(new Node); shared_ptrNode n2(new Node); n1-_next n2; n2-_prev n1; //出作用域n1、n2计数都减到1永远不为0 →内存泄漏 return 0; }2.6 std::weak_ptrC11中提供的弱引用智能指针特点1. 不增加 share_ptr 的引用计数只作为观察者2. 不能直接解引用访问堆资源没有独占、共享所以权3. 专门用来打破 share_ptr 循环引用4. 可以检测资源是否已经被释放expired()对比表格智能指针所有权引用计数能否拷贝移动主要用途unique_ptr独占无不能支持move资源唯一管理代替裸指针shared_ptr共享有能支持move多人共用一份堆资源weak_ptr弱引用无所有权不计数能支持move打破循环引用、观测资源
返回列表