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

深入C++:operator new与operator delete重载探秘

目录

一、C++ 内存管理初印象

二、operator new 和 operator delete 的基本原理

(一)operator new 的工作机制

(二)operator delete 的工作机制

三、为什么要重载 operator new 和 operator delete

(一)优化内存分配效率

(二)实现自定义内存管理策略

四、如何重载 operator new 和 operator delete

(一)重载的基本语法和规则

(二)类专属的 operator new 和 operator delete 重载

(三)全局 operator new 和 operator delete 重载

五、重载 operator new 和 operator delete 的注意事项

(一)配对使用原则

(二)处理内存分配失败的情况

(三)避免与 STL 库冲突

六、实际案例分析

(一)内存池的实现

(二)性能对比测试

七、总结与展望


一、C++ 内存管理初印象

        在 C++ 编程的世界里,内存管理堪称基石般的存在,其重要性怎么强调都不为过。内存管理的优劣,直接关乎程序的性能表现、稳定性以及资源利用率。一旦内存管理出现问题,比如内存泄漏,随着程序运行时间的增加,内存不断被消耗却得不到释放,最终会导致系统内存耗尽,程序崩溃;再比如野指针的产生,对其进行操作可能会导致程序访问非法内存地址,引发未定义行为,让程序出现各种难以调试的诡异问题。

        C++ 中,动态内存的分配和释放主要依靠new和delete操作符 。当我们使用new创建一个对象时,它会在堆上为该对象分配内存,并调用对象的构造函数进行初始化。例如:

int* num = new int(5);

        这行代码在堆上分配了一个int类型的内存空间,并将其初始化为 5 ,num指针指向这块内存。

而delete的作用则是释放由new分配的内存,并调用对象的析构函数。像这样:

delete num;

        这就释放了num指向的内存空间,防止内存泄漏。

        那operator new和operator delete函数又是什么呢?其实,new和delete操作符背后调用的就是operator new和operator delete函数 。operator new负责分配内存,当new操作符被使用时,它首先调用operator new函数来获取所需的内存空间,然后在这块内存上调用对象的构造函数;operator delete则负责释放内存,delete操作符会先调用对象的析构函数,然后调用operator delete函数来释放内存。简单来说,operator new和operator delete是内存分配和释放的底层实现函数,而new和delete操作符则为我们提供了更高级、更方便的语法糖,让我们能更简洁地进行内存管理操作。

二、operator new 和 operator delete 的基本原理

(一)operator new 的工作机制

        operator new的主要职责是在堆上分配指定大小的内存空间 。它的实现其实是基于 C 语言的malloc函数。当我们调用operator new时,它会尝试通过malloc来申请内存 。比如下面这段代码:

void* operator new(size_t size) {void* p = malloc(size);if (!p) {// 处理内存分配失败的情况}return p;}

        在这个函数中,malloc尝试分配size大小的内存空间 。如果malloc成功分配内存,operator new就直接返回指向这块内存的指针;但如果malloc失败,也就是返回了NULL指针,operator new就会着手处理内存分配失败的情况 。

        通常,operator new在内存分配失败时,会尝试执行一些空间不足的应对措施 。比如,它可能会调用用户设置的new_handler函数 。这个new_handler函数是用户自定义的,用于处理内存不足的情况。它可以尝试释放一些其他的内存,以便为当前的内存分配请求腾出空间;或者它也可以抛出异常,表明内存分配失败 。如果用户没有设置new_handler函数,operator new就会抛出std::bad_alloc异常 ,这是 C++ 标准库定义的用于表示内存分配失败的异常类型 。

(二)operator delete 的工作机制

        operator delete的作用是释放由operator new分配的内存空间 。它的工作过程和free函数紧密相关 。operator delete的基本实现如下:

void operator delete(void* p) {if (p) {free(p);}}

        从这段代码可以看出,当operator delete接收到一个非空指针p时,它会调用free函数来释放p指向的内存空间 。free函数是 C 语言标准库中的函数,专门用于释放由malloc、calloc或realloc分配的内存 。在operator delete中调用free,就完成了内存的释放操作 。

        需要注意的是,在释放内存之前,operator delete会先检查指针p是否为NULL 。如果p是NULL,说明没有实际的内存需要释放,operator delete会直接返回,不执行任何操作 。这是一种常见的安全检查机制,避免了对空指针进行无效的释放操作,防止程序出现未定义行为 。

三、为什么要重载 operator new 和 operator delete

(一)优化内存分配效率

        在程序运行过程中,频繁的内存申请和释放操作会带来不小的开销。以链表节点的内存分配为例,如果每次创建和销毁链表节点都使用默认的operator new和operator delete ,就会频繁地与操作系统的内存管理机制交互,导致效率低下。

        假设我们有一个链表,链表中的节点频繁地被创建和删除。在默认情况下,每次创建一个节点,operator new都会向操作系统申请内存 ,而每次删除节点,operator delete又会将内存归还给操作系统 。这一来一回的操作不仅涉及系统调用,还可能导致内存碎片化,降低内存的使用效率。

        通过重载operator new和operator delete ,我们可以实现内存池技术 。内存池就像是一个预先准备好的内存仓库,我们在程序开始时一次性向操作系统申请一大块内存,将其作为内存池 。当需要创建链表节点时,从内存池中分配内存,而不是每次都向操作系统申请;当节点被销毁时,将内存放回内存池,而不是归还给操作系统 。这样,就避免了频繁的系统调用,大大提高了内存分配和释放的效率 。例如:

#include <memory>#include <iostream>struct ListNode {ListNode* _prev;ListNode* _next;int _data;// 重载operator newvoid* operator new(size_t size) {static std::allocator<ListNode> alloc;void* p = alloc.allocate(1);std::cout << "从内存池分配内存" << std::endl;return p;}// 重载operator deletevoid operator delete(void* p) {static std::allocator<ListNode> alloc;alloc.deallocate((ListNode*)p, 1);std::cout << "将内存放回内存池" << std::endl;}};

        在这个例子中,ListNode结构体重载了operator new和operator delete 。在operator new中,使用std::allocator从内存池中分配内存 ;在operator delete中,将内存归还给内存池 。通过这种方式,链表节点的内存分配和释放效率得到了显著提升 。

(二)实现自定义内存管理策略

        在一些特定的应用场景中,默认的内存管理策略无法满足需求,这时就需要重载operator new和operator

相关文章:

深入C++:operator new与operator delete重载探秘

目录 一、C++ 内存管理初印象 二、operator new 和 operator delete 的基本原理 (一)operator new 的工作机制 (二)operator delete 的工作机制 三、为什么要重载 operator new 和 operator delete (一)优化内存分配效率 (二)实现自定义内存管理策略 四、如何重…...

4小时速通shell外加100例

&#x1f525; Shell 基础——从入门到精通 &#x1f680; &#x1f331; 第一章&#xff1a;Shell&#xff0c;简单说&#xff01; &#x1f476; 什么是Shell&#xff1f;它到底能做什么&#xff1f;这章让你快速了解Shell的强大之处&#xff01; &#x1f476; 什么是Shell…...

文字变央视级语音转换工具

大家在制作短视频、广告宣传、有声读物、自媒体配音、学习辅助等场景的时候&#xff0c;经常会需要用到配音来增强视频的表现力和吸引力。然而&#xff0c;市面上的一些配音软件往往需要收费&#xff0c;这对于很多初学者或者预算有限的朋友来说&#xff0c;无疑增加了一定的负…...

优先队列-小根堆留坑

给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2] 示例 2: 输入: nums [1], k 1 输出: [1] 提示&#xff1a; 1 < nums.length < 105 k 的…...

Vue 表单输入绑定,双向绑定

一、v-model 指令 用于Vue 表单双向绑定 用户Vue 组件属性双向绑定 v-model 还可以用于各种不同类型的输入&#xff0c;<textarea>、<select> 元素。它会根据所使用的元素自动使用对应的 DOM 属性和事件组合&#xff1a; 文本类型的 <input> 和 <text…...

日志2333

Pss-9 这一关考察的是时间盲注 先练习几个常见命令语句&#xff1a; select sleep(5);--延迟5s输出结果 if &#xff08;1>0,ture,false&#xff09;;--输出‘ture’ /if &#xff08;1<0,ture,false&#xff09;;--输出‘false’ select ascii()/select ord()返回字…...

spring MVC 介绍

Spring MVC 是 Spring 框架中用于构建 Web 应用的核心模块&#xff0c;基于 MVC 设计模式&#xff08;Model-View-Controller&#xff09;实现。以下是其核心概念的整理&#xff1a; 1. MVC 设计模式 • Model&#xff08;模型&#xff09;&#xff1a;封装业务数据和业务逻辑…...

计算机的基本组合和工作原理

计算机的基本组成和工作原理可以概括为以下几个核心部分&#xff1a; 一、计算机的基本组成&#xff08;冯诺依曼体系结构&#xff09; 现代计算机基于冯诺依曼体系结构&#xff0c;主要由以下五大部件组成&#xff1a; 控制器&#xff08;Control Unit, CU&#xff09; 功能&…...

美国国家数据浮标中心(NDBC)

No.大剑师精品GIS教程推荐0地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 1Openlayers 【入门教程】 - 【源代码示例 300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3MapboxGL【入门教程】 - 【源代码图文示例150】 4Cesium 【入门教程】…...

【计算机网络】网络简介

文章目录 1. 局域网与广域网1.1 局域网1.2 广域网 2. 路由器和交换机3. 五元组3.1 IP和端口3.2 协议3.3 协议分层 4. OSI七层网络协议5. TCP/IP五层模型5.1 TCP/IP模型介绍5.2 网络设备所在分层 6. 封装与分用6.1 数据包的称谓6.2 封装6.3 分用 1. 局域网与广域网 1.1 局域网 …...

Vue.js 模板语法全解析:从基础到实战应用

引言 在 Vue.js 的开发体系中&#xff0c;模板语法是构建用户界面的核心要素&#xff0c;它让开发者能够高效地将数据与 DOM 进行绑定&#xff0c;实现动态交互效果。通过对《Vue.js 快速入门实战》中关于 Vue 项目部署章节&#xff08;实际围绕 Vue 模板语法展开&#xff09;…...

python+ffmpeg给音频添加背景音乐

说明&#xff1a; 我希望用python&#xff0c;将name.mp3这段录音文件&#xff0c;添加背景音乐&#xff0c;bg.mp3&#xff0c;然后生成新的文件 step1: 添加依赖 pip install pydubstep2:下载ffmpeg 1.打开windows powershell &#xff0c;管理员运行 2.winget install ff…...

bootstrap 表格插件bootstrap table 的使用经验谈!

最近在开发一个物业管理软件&#xff0c;其中用到bootstrap 的模态框。同时需要获取表格数据。用传统的方法&#xff0c;本人不想用&#xff0c;考虑到bootstrap应该有获取表格数据的方法&#xff0c;结果发现要想实现获取表格数据功能&#xff0c;需要通过bootstrap的插件实现…...

Spring Boot框架识别

1. 通过icon图标进行识别 2、如果 web 应用开发者没有修改 SpringBoot Web 应用的默认 4xx、5xx 报错页面&#xff0c;那么当 web 应用程序出现 4xx、5xx 错误时&#xff0c;会报错如下图&#xff1a; 其他页面 工具一把梭哈...

【MySQL】【已解决】Windows安装MySQL8.0时的报错解决方案

一、引言 先说一些没用的话&#xff0c;据说安装MySQL是无数数据库初学者的噩梦&#xff0c;我在安装的时候也是查了很多资料&#xff0c;看了很多博客&#xff0c;但是很多毕竟每个人的电脑有各自不同的情况&#xff0c;大家的报错也不尽相同&#xff0c;所以也是很长时间之后…...

基于linux平台的C语言入门教程(7)类型转换

文章目录 1. 什么是类型转换&#xff1f;2. 隐式类型转换隐式类型转换的规则&#xff1a; 3. 显式类型转换显式类型转换的语法&#xff1a; 4. 示例代码代码解析&#xff1a;输出结果&#xff1a; 5. 常见问题问题 1&#xff1a;隐式类型转换会导致数据丢失吗&#xff1f;问题 …...

MES汽车零部件制造生产监控看板大屏

废话不多说&#xff0c;直接上效果 预览效果请在大的显示器查看&#xff0c;笔记本可能有点变形 MES汽车零部件制造生产监控看板大屏 纯html写的项目结构如下 主要代码分享 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UT…...

晶鑫股份迈向敏捷BI之路,永洪科技助力启程

数据驱动的时代&#xff0c;每一次技术的创新和突破都在为企业的发展注入新的动力。而敏捷性也不再是选择&#xff0c;是企业生存与发展的必要条件。作为连续5年获得中国敏捷BI第一名的永洪科技&#xff0c;通过不断地在数据技术领域深耕细作&#xff0c;再次迎来了行业内的关注…...

Browser Use Web UI 本地部署完全指南:从入门到精通

文章目录 引言一、项目概述1.1 核心功能1.2 技术特点 二、环境准备2.1 系统要求2.2 必要工具 三、详细部署步骤3.1 获取项目代码3.2 配置 Python 环境3.3 安装项目依赖3.4 环境配置3.5 启动应用 四、DeepSeek-V1 模型配置4.1 基础配置 五、执行Browser Use六、故障排查指南6.1 …...

Java单例模式、懒汉模式、饿汉模式和懒加载

好的&#xff01;我们来详细讲解单例模式、懒汉模式、饿汉模式和懒加载&#xff0c;争取让你看完就懂&#xff01; &#x1f7e6; 一、单例模式&#xff08;Singleton Pattern&#xff09; 定义&#xff1a;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 应用场…...

Linux 内核源码阅读——ipv4

Linux 内核源码阅读——ipv4 综述 在 Linux 内核中&#xff0c;IPv4 协议的实现主要分布在 net/ipv4/ 目录下。以下是一些关键的源文件及其作用&#xff1a; 1. 协议栈核心 net/ipv4/ip_input.c&#xff1a;处理接收到的 IPv4 数据包&#xff08;输入路径&#xff09;。net…...

nginx5天时间从0到熟练掌握学习计划

要在 5 天内熟练地在项目中使用 Nginx&#xff0c;需要制定一个高效的学习计划&#xff0c;重点学习 Nginx 的核心功能和实际应用。以下是一个详细的学习计划&#xff0c;帮助你从零开始掌握 Nginx。 学习目标 掌握 Nginx 的基本概念和安装方法。能够配置 Nginx 托管静态文件、…...

宝塔平替!轻量级开源 Linux 管理面板 mdserver-web

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 想必很多人刚接触 Linux 云服务器的时候都听过或者用过宝塔面板&#xff0c;对于小白来说&#xff0c;使用面板大大降低了服务器运维的难度&#xff0c;一键安装 LNMP 环境就可以建站了&#xff0c;像是 N…...

蓝桥杯 劲舞团

问题描述 小蓝最近迷上了一款名为 “劲舞团” 的游戏。 在游戏中&#xff0c;只要按照给出的键位提示依次按出对应的键位&#xff0c;游戏人物便可以跟随节奏跳舞。 对于连续的 K 次正确敲击&#xff0c;如果任意连续两次敲击之间的时间间隔都小于等于 1 秒&#xff08;即 1…...

基于springboot+vue的网络海鲜市场

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

QT开发(6)--信号和槽

这里写目录标题 1. 信号和槽概述信号的本质槽的本质 2. 信号和槽的使用2.1 连接信号和槽2.2 文档查询 3.自定义信号和槽3.1 自定义槽3.2 自定义信号3.3 带参数的信号和槽 4. 信号和槽的断开 1. 信号和槽概述 在Qt中&#xff0c;⽤⼾和控件的每次交互过程称为⼀个事件。⽐如&quo…...

Linux部署DHCP服务脚本

#!/bin/bash #部署DHCP服务 #userli 20250319#检查是否为root用户 if[ "$USER" ! "root" ] thenecho "错误&#xff1a;非root用户&#xff0c;权限不足&#xff01;"exit 0 fi#配置网络环境 read -ep "请给本机配置一个IP地址(不…...

Dervy数据库

Derby 和 Sqlite 数据库都是无需安装的数据库 Derby 和 Sqlite 数据库的配置与使用_derby sqlite-CSDN博客 Derby数据库简明教程_原味吐司-腾讯云---开发者社区 下载 对于jdk1.8及以上 Apache Derby 10.14.2.0 Release 进入bin 找到 启动服务端 进入bin目录 实际上是启…...

Pythonic编程设计风格解析

Python 作为一种“优雅”、“简洁”、“明确”的编程语言&#xff0c;自诞生以来便以其极强的可读性和简洁的语法风靡全球。然而&#xff0c;真正掌握 Python 并不仅仅是会写 Python 代码&#xff0c;更在于是否写出了Pythonic 风格的代码。什么是 Pythonic&#xff1f;Guido v…...

优化 SQL 语句方向和提升性能技巧

优化 SQL 语句是提升 MySQL 性能的关键步骤之一。通过优化 SQL 语句,可以减少查询时间、降低服务器负载、提高系统吞吐量。以下是优化 SQL 语句的方法、策略和技巧: 一、优化 SQL 语句的方法 1. 使用 EXPLAIN 分析查询 作用:查看 SQL 语句的执行计划,了解查询是如何执行的…...