当前位置: 首页 > news >正文

智能指针笔记

智能指针,利用class类对象销毁的时候自动调用析构函数,去把delete ptr的操作放在析构函数里,去实现自动释放指针里的资源


RAII是ResourceAcquisition Is Initialization的缩写,他是⼀种管理资源的类的设计思想,本质是 ⼀种利⽤对象⽣命周期来管理获取到的动态资源,避免资源泄漏,这⾥的资源可以是内存、⽂件指 针、⽹络连接、互斥锁等等。RAII在获取资源时把资源委托给⼀个对象,接着控制对资源的访问, 资源在对象的⽣命周期内始终保持有效,最后在对象析构的时候释放资源,这样保障了资源的正常 释放,避免资源泄漏问题。

智能指针类除了满⾜RAII的设计思路,还要⽅便资源的访问,所以智能指针类还会想迭代器类⼀ 样,重载 operator*/operator->/operator[] 等运算符,⽅便访问资源。


unique_ptr //唯一指针

只有移动,没有拷贝,

shared_ptr //共享指针,引用计数的指针

有移动,有拷贝,引用计数来判断是否对所管理的资源进行delete

weak_ptr //弱指针,解决循环引用内存泄漏问题,配合shared_ptr使用

delete ptr /delete[] ptr; shared和unique的删除器

unique_ptr和shared_ptr都有

unique_ptr<Date[]> up1(new Date[5]);

shared_ptr<Date[]> sp1(new Date[5]);

的用法,

此外,shared的删除器是通过构造函数的第二个参数传入,而unique还要传入模板参数的第二个类型,

struct Date
{int _year;int _month;int _day;Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){}~Date(){cout << "~Date()" << endl;}};
template<class T>
void DeleteArrayFunc(T* ptr)
{delete[] ptr;
}
template<class T>
class DeleteArray
{
public:void operator()(T* ptr){delete[] ptr;}
};
class Fclose
{
public:void operator()(FILE* ptr){cout << "fclose:" << ptr << endl;fclose(ptr);}
};
int main()
{//这样实现程序会崩溃// unique_ptr<Date> up1(new Date[10]);// shared_ptr<Date> sp1(new Date[10]);// 解决⽅案1// 因为new[]经常使⽤,所以unique_ptr和shared_ptr// 实现了⼀个特化版本,这个特化版本析构时⽤的delete[]unique_ptr<Date[]> up1(new Date[5]);shared_ptr<Date[]> sp1(new Date[5]);// 解决⽅案2// 仿函数对象做删除器//unique_ptr<Date, DeleteArray<Date>> up2(new Date[5], DeleteArray<Date>());// unique_ptr和shared_ptr⽀持删除器的⽅式有所不同// unique_ptr是在类模板参数⽀持的,shared_ptr是构造函数参数⽀持的// 这⾥没有使⽤相同的⽅式还是挺坑的// 使⽤仿函数unique_ptr可以不在构造函数传递,因为仿函数类型构造的对象直接就可以调⽤// 但是下⾯的函数指针和lambda的类型不可以unique_ptr<Date, DeleteArray<Date>> up2(new Date[5]);shared_ptr<Date> sp2(new Date[5], DeleteArray<Date>());// 函数指针做删除器unique_ptr<Date, void(*)(Date*)> up3(new Date[5], DeleteArrayFunc<Date>);shared_ptr<Date> sp3(new Date[5], DeleteArrayFunc<Date>);// lambda表达式做删除器auto delArrOBJ = [](Date* ptr) {delete[] ptr; };unique_ptr<Date, decltype(delArrOBJ)> up4(new Date[5], delArrOBJ);shared_ptr<Date> sp4(new Date[5], delArrOBJ);// 实现其他资源管理的删除器shared_ptr<FILE> sp5(fopen("Test.cpp", "r"), Fclose());shared_ptr<FILE> sp6(fopen("Test.cpp", "r"), [](FILE* ptr) {cout << "fclose:" << ptr << endl;fclose(ptr);});return 0;
}

shared_ptr的循环引用缺陷

经典例子,你保我,我保你

#include <iostream>
#include <memory>class Node {
public:std::shared_ptr<Node> prev;  // 指向前一个节点std::shared_ptr<Node> next;  // 指向后一个节点~Node() {std::cout << "Node destroyed" << std::endl;}
};int main() {// 创建两个节点,形成循环引用auto node1 = std::make_shared<Node>();auto node2 = std::make_shared<Node>();node1->next = node2;  // node1 引用 node2node2->prev = node1;  // node2 引用 node1// main函数结束时...// node1 和 node2 的引用计数都为2(自身+对方)// 因此它们的析构函数不会被调用,导致内存泄漏return 0;
}

相关文章:

  • CST软件如何获取二极管的IV曲线
  • 边缘计算:技术概念与应用详解
  • 黑马Java基础笔记-9
  • C++23 views::chunk_by (P2443R1) 详解
  • Linux网络编程day8本地套接字
  • 【LeetCode Solutions】LeetCode 176 ~ 180 题解
  • Bearer Token的神秘面纱:深入解析HTTP认证头的设计哲学
  • rust-candle学习笔记11-实现一个简单的自注意力
  • Excel图表 vs 专业可视化工具:差距有多大?内容摘要
  • 浅蓝色调风格人像自拍Lr调色预设,手机滤镜PS+Lightroom预设下载!
  • 【Survival Analysis】【机器学习】【3】deepseek流程图
  • RDD转换算子案例
  • 【Python 字典(Dictionary)】
  • Baklib知识中台引领服务智能跃迁
  • ‌云原生CAE软件
  • Nacos源码—7.Nacos升级gRPC分析四
  • 【C/C++】范围for循环
  • 如何解决按钮重复点击
  • Java高频基础面试题
  • 画家沈燕的山水实验:在传统皴法里植入时代密码
  • 白宫启动“返乡计划” ,鼓励非法移民自愿离开美国
  • 国家出口管制工作协调机制办公室部署开展打击战略矿产走私出口专项行动
  • 大四本科生已发14篇SCI论文?重庆大学:成立工作组核实
  • 硅料巨亏后弘元绿能割肉求生:逾12亿元内蒙古公司股权转让协鑫
  • 国家卫健委:有条件的二级及以上综合医院要开设老年医学科
  • 世界人形机器人运动会将在北京“双奥场馆”举行