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

Item16--`new` 与 `delete` 的对应规则

👨‍🏫 条款 16 详解:newdelete 的对应规则

1. 核心规则回顾

分配 (new) 释放 (delete) 语义
new T delete p 分配/释放单个对象
new T[ ] delete [ ] p 分配/释放对象数组

违反这条规则会导致未定义行为 (Undefined Behavior, UB)。 在 C++ 中,未定义行为意味着程序的行为是不可预测的,可能表现为内存泄漏、数据损坏或程序崩溃。

2. 深入探究:为什么会出错?

当涉及拥有析构函数的类类型对象时,形式不匹配的问题最为严重。

A. 错误一:new T[] 配上 delete p

// 假设 ResourceHolder 是一个拥有析构函数的类
ResourceHolder* pArray = new ResourceHolder[5];
// ...
delete pArray; // 错误: new[] 却用了 delete

🔍 原理分析:

  1. new ResourceHolder[5] 的操作: 编译器在分配内存时,通常会在实际对象数组之前(或之后)预留一块空间,用于存储数组的元素个数(即 5)。接着,它会循环调用 5 次 ResourceHolder构造函数
  2. delete pArray 的操作: 运行时看到没有方括号的 delete,它假设这是单个对象的释放。它执行以下操作:
    • 只调用一次 ResourceHolder析构函数(针对数组的第一个元素 pArray[0])。
    • 释放整个内存块。

⚠️ 后果:

  • 资源泄漏: pArray[1]pArray[4] 这 4 个对象的析构函数没有被调用。如果这些对象在析构函数中释放了资源(如文件句柄、网络连接或内部堆内存),这些资源将无法被释放,造成典型的资源泄漏

B. 错误二:new T 配上 delete[] p

ResourceHolder* pSingle = new ResourceHolder;
// ...
delete [] pSingle; // 错误: new 却用了 delete[]

🔍 原理分析:

  1. new ResourceHolder 的操作: 仅为单个对象分配内存,并调用一次构造函数。内存块中没有存储数组大小的额外信息。
  2. delete [] pSingle 的操作: 运行时看到带方括号的 delete[],它会去寻找存储在内存块开头的数组大小信息。由于没有这个信息,它会读取该内存位置上的垃圾数据,并将其误认为是数组大小。

⚠️ 后果:

  • 程序崩溃: 运行时可能会基于这个错误的“大小”多次调用析构函数,这不仅是不必要的,而且极有可能访问到不属于该对象的内存,导致堆损坏程序立即崩溃

3. 解决方案:使用智能指针

条款 16 是 C++ 内存管理中一个常见的错误源。为了彻底避免这类问题,最好的办法是不要自己管理内存

推荐做法:使用 std::unique_ptr 管理动态分配的内存。

自 C++11 起,std::unique_ptr 被设计成能安全地处理单个对象和数组:

场景 代码 自动释放
单个对象 auto p = std::make_unique<T>(); p 超出作用域时,自动调用 delete p.release()
对象数组 auto p = std::make_unique<T[]>(N); p 超出作用域时,自动调用 delete [] p.release()
// 推荐示例:
#include <memory>// 单个对象
auto p1 = std::make_unique<ResourceHolder>(); 
// p1 离开作用域时,自动调用 delete// 对象数组 (N=5)
auto p2 = std::make_unique<ResourceHolder[]>(5);
// p2 离开作用域时,自动调用 delete[] (且会调用所有5个析构函数)

使用 std::unique_ptr 不仅保证了异常安全(即使发生异常也会释放资源),还自动选择了正确的 delete 形式,完全消除了条款 16 中描述的风险。

http://www.rkmt.cn/news/127910.html

相关文章:

  • 预见2026:家居新品首秀平台选择战略——五大核心展会深度评估与推荐 - 匠子网络
  • 国外软件,安装即时专业版!
  • 个人投资者的落地路径:从“说人话,做量化”到实盘前的三道关
  • item13--使用对象管理资源
  • sub_match
  • python django flask酒店客房管理系统数据可视化分析系统_gq8885n3--论文md5
  • python django flask鹿幸公司员工食堂在线点餐餐饮餐桌预约管理系统的设计与实现_utcnqqs0--论文
  • error_code
  • 好用的大型牛场水滴粉碎机技术强的
  • function bind
  • Item6--若不想使用编译器自动生成的函数,就该明确拒绝
  • 我发现LLM解析基因数据优化抗癌药剂量,患者副作用直降40%
  • 线程(1)
  • 日记12.16
  • 信息与关系:涌现的三大核心原则
  • 论文AIGC查重率高怎么办?6个降AI率工具和技巧,AI率从100%降到3%! - 还在做实验的师兄
  • 离散化遍历
  • 28
  • 人工智能与大数据:智能决策的新时代 - 教程
  • 花边服饰银发红眸者山间近景
  • 互联网大厂Java面试:从Spring Boot到微服务架构的技术探讨
  • 性价比高的老房换新实用门窗品牌精选指南排名
  • 12月20日总结 - 作业----
  • 老牌软件,输入序列号可激活商业版!
  • 熬夜刷手机不愿睡觉,这是一种心理问题吗?
  • enum class
  • 专业的康有利到家理疗小程序哪家好
  • 云计算IP大纲
  • 回眸的狼耳圣女与荧光百合
  • 第四章 作业