条款51:编写 new 和 delete 时需固守常规( Adhere to convention when writing new and delete)

news/2025/1/8 5:45:55/

条款51:编写 new 和 delete 时需固守常规

1.1 new

C++要求new运算符即使在请求0字节时也返回一个合法的指针。

void* operator new(std::size_t size) { // 你的new操作符可能需要额外的参数using namespace std; if (size == 0) { 	// 处理0字节请求,size = 1; 	// 将它们视为1字节请求}  while (true) {... //尝试分配size个字节;if (分配成功)return (指向内存的指针);// 分配失败;找出当前的new-handler函数new_handler globalHandler = get_new_handler(0);set_new_handler(globalHandler);if (globalHandler) (*globalHandler)();else throw std::bad_alloc();}
}

1.2 成员函数new

成员函数operator new,会被派生类继承。

class Base {
public:static void* operator new(std::size_t size);...
};
class Derived : public Base // 派生类没有声明new运算符
{...
}; 
Derived* p = new Derived; // 调用 Base::operator new!

派生类和基类的大小可能不同,处理这种情况的最佳方法是将请求“错误”内存大小的调用丢弃给标准new运算符。

void* Base::operator new(std::size_t size) 
{
//sizeof(Base)永远不会是0if (size != sizeof(Base)) // 如果大小是“错误的”,return ::operator new(size); // 采用标准operator new处理请求... // 否则在这里处理请求
}

1.3 operator new[]

实现operator new[](array new)时,唯一能做的就是分配一块原始内存,实际上甚至无法计算这个数组将含有多少个元素(当派生类较大时,(请求的字节数)/sizeof(Base) 并不正确;并且数组还可能包含额外的内容,例如数组大小)。

1.4 delete

对于delete运算符,事情就简单多了。你需要记住的是,C++保证delete空指针总是安全的,所以你需要遵守这个保证。

void operator delete(void* rawMemory) noexcept
{if (rawMemory == 0) return; // 如果空指针正在被删除,什么都不做... // 释放rawMemory指向的内存;
}

1.5 成员函数delete

成员函数版本也很简单,只需要将大小“错误”的delete行为转交给标准的operator delete:

class Base { // 和之前一样,但现在声明了delete运算符
public:  static void* operator new(std::size_t size);static void operator delete(void* rawMemory, std::size_t size) noexcept;...
};
void Base::operator delete(void* rawMemory, std::size_t size) noexcept
{if (rawMemory == 0) return; // 检查空指针if (size != sizeof(Base)) { // 如果大小是“错误的”,使用标准delete运算符::operator delete(rawMemory);  return; }... // 释放rawMemory指向的内存;return;//如果被释放的对象派生自某个缺少虚析构函数的基类,那么 C++ 传给operator delete的size可能不正确
}

1.6 总结

  1. new运算符应该包含一个尝试分配内存的无限循环,如果它不能满足内存请求,应该调用new-handler,应该处理0字节的请求,类专用的版本应该处理比预期更大的块的请求。
  2. 如果传递给delete运算符的指针是null,那么它什么也不会做。类专用版本应该处理比预期更大的块。

http://www.ppmy.cn/news/1560644.html

相关文章

小程序租赁系统开发的优势与应用探索

内容概要 在如今这个数码科技飞速发展的时代,小程序租赁系统开发仿佛是一张神奇的魔法卡,能让租赁体验变得顺畅如丝。想象一下,无论你需要租用什么,从单车到房屋,甚至是派对用品,只需动动手指,…

深入剖析MySQL数据库架构:核心组件、存储引擎与优化策略(三)

存储引擎(9--5版本,11--8版本) 存储引擎Innodb InnoDB支持事务、分布式(并发) 使用InnoDB时,会将数据表分为.frm 和 idb两个文件进行存储。 InnoDB采用MVCC(多版本并发控制)来支持高并发,InnoDB实现了四个隔离级别&a…

露营小程序搭建有哪些步骤?小程序里面可以找个露营搭子

露营不仅仅是走进大自然的旅程,它也成为了一种社交和体验式的活动。随着小程序的普及,露营活动也越来越多地开始在线上开展。通过搭建一个露营小程序,商家不仅可以为用户提供更多的露营选择,还可以帮助他们找到合适的露营搭子。那…

【机器学习】机器学习的基本分类-半监督学习-Ladder Networks

Ladder Networks 是一种半监督学习模型,通过将无监督学习与监督学习相结合,在标记数据较少的情况下实现高效的学习。它最初由 A. Rasmus 等人在 2015 年提出,特别适合深度学习任务,如图像分类或自然语言处理。 核心思想 Ladder N…

STM32-BKP备份寄存器RTC实时时钟

一、原理 Unix: 一些系统是使用32bit有符号数存储,实际范围为-2,147,483,648到2,147,483,647‌即~ 经过计算int32数据会在2038年1月19日溢出,可以看到转换的为北京时间。 STM32的时间戳为无符号时间戳。 我们需要把秒计数器的时间通过计算…

第五章 起航 01 一年之计

开年第一周,要做最重要的事情。 什么是重要的事?我认为不是重点项目,而是从我们整个在公司工作期间、甚至整个职业生涯视角来看,学习成长才是最重要的。 一、分享计划 前一年确定了每人每年做两次分享,对大家有点挑…

玩转OCR | 腾讯云智能结构化OCR初次体验

目录 一、什么是OCR(需要了解) 二、产品概述与核心优势 产品概述 智能结构化能做什么 举例说明(选看) 1、物流单据识别 2、常见证件识别 3、票据单据识别 4、行业材料识别 三、产品特性 高精度 泛化性 易用性 四、…

【每日学点鸿蒙知识】深色模式、Webview查看版本、window设置亮度、List缓存节点更新、预编译JS

1、HarmonyOS 深色模式下canvas绘制通过resourcemanager.getColor不是实际dark模式下的颜色? 深色模式下canvas绘制通过resourcemanager.getColor不是实际dark模式下的颜色 正确获取到资源resourcemanager. getColorSync($r(‘app.color.test_color’).id);深色模…