0

0

C++的new和delete运算符具体是如何工作的

P粉602998670

P粉602998670

发布时间:2025-09-02 10:39:01

|

1004人浏览过

|

来源于php中文网

原创

new运算符先计算内存大小,调用operator new分配堆内存,再调用构造函数初始化对象;delete先调用析构函数清理资源,再调用operator delete释放内存。两者必须配对使用,且new对应delete,new[]对应delete[]。与malloc/free不同,new/delete具备类型安全、自动调用构造/析构函数、可重载等特性,推荐在C++中优先使用。自定义operator new/delete可用于内存池、调试或嵌入式场景,但需确保内存分配与释放匹配。动态内存适用于对象大小未知、生命周期超出作用域或需灵活管理大量对象的情况。为避免内存泄漏,应使用智能指针、养成良好习惯并借助工具检测。

c++的new和delete运算符具体是如何工作的

C++的

new
delete
运算符,说白了,就是用来动态分配和释放内存的。
new
负责找一块地方给你用,
delete
负责把用完的地方还回去。但这背后的细节,其实挺有意思的。

解决方案

new
运算符干的事情,大致可以分为三步:

  1. 计算所需内存大小:这步编译器会自动搞定,根据你
    new
    的对象类型,算出需要多少字节。
  2. 分配内存:这才是
    new
    的核心。它会调用一个叫做
    operator new
    的函数,这个函数负责在堆(heap)上找到一块足够大的连续内存块。如果找不到,通常会抛出一个
    std::bad_alloc
    异常(当然,你也可以自定义
    new
    的行为,让它返回空指针)。
  3. 初始化对象:拿到内存后,
    new
    会调用对象的构造函数,在分配到的内存上“盖房子”,把对象真正地创建出来。

delete
运算符则相反,它也分三步:

立即学习C++免费学习笔记(深入)”;

  1. 调用析构函数:先调用对象的析构函数,把对象“拆房子”,清理对象占用的资源。
  2. 释放内存:然后调用
    operator delete
    函数,把之前
    new
    分配的内存块还给堆,这样这块内存就可以被再次利用了。
  3. 安全处理:虽然不是必须,但好的习惯是将指针设置为
    nullptr
    ,防止悬挂指针。

需要注意的是,

new
delete
必须配对使用,而且要对应正确的形式。比如,用
new
分配的数组,要用
delete[]
释放,否则可能会导致内存泄漏或者程序崩溃。

new
malloc
有什么区别

这是个经典问题。

malloc
是C语言的函数,而
new
是C++的运算符,它们在内存分配上都能实现类似的功能,但区别还是挺大的。

  • 类型安全
    new
    是类型安全的,它会返回一个指向正确类型的指针,并且在编译时进行类型检查。
    malloc
    返回的是
    void*
    ,需要手动强制类型转换,容易出错。
  • 构造/析构函数
    new
    会自动调用对象的构造函数进行初始化,
    delete
    会自动调用析构函数进行清理。
    malloc
    free
    则不会调用构造函数和析构函数,对于C++对象来说,这非常重要,因为很多资源清理工作需要在析构函数中完成。
  • 重载
    new
    delete
    可以被重载,可以自定义内存分配的行为。
    malloc
    free
    则不能被重载。
  • 异常处理
    new
    在分配失败时会抛出异常,而
    malloc
    返回
    NULL

简单来说,C++中应该尽量使用

new
delete
,而不是
malloc
free

如何自定义
new
delete

C++允许你重载

operator new
operator delete
,这样你就可以自定义内存分配的行为。这在某些特殊场景下很有用,比如:

  • 内存池:为了提高内存分配的效率,可以实现一个内存池,预先分配一块大的内存,然后从中分配小块的内存。
  • 调试:可以重载
    new
    delete
    来跟踪内存分配情况,检测内存泄漏。
  • 嵌入式系统:在资源受限的嵌入式系统中,可能需要自定义内存分配策略。

自定义

new
delete
的基本形式如下:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载
void* operator new(size_t size) {
  // 分配内存的逻辑
  void* p = malloc(size);
  if (!p) throw std::bad_alloc();
  return p;
}

void operator delete(void* p) noexcept {
  // 释放内存的逻辑
  free(p);
}

void* operator new[](size_t size) { // for array
  // 分配内存的逻辑
  void* p = malloc(size);
  if (!p) throw std::bad_alloc();
  return p;
}

void operator delete[](void* p) noexcept { // for array
  // 释放内存的逻辑
  free(p);
}

需要注意的是,自定义

new
delete
时,要确保分配和释放的内存是匹配的,否则会导致严重的错误。

什么时候应该使用
new
delete

动态内存分配并非总是最佳选择。在以下情况下,考虑使用

new
delete

  • 对象的大小在编译时未知:如果对象的大小需要在运行时才能确定,例如,根据用户的输入动态创建一个数组,那么就需要使用
    new
    来分配内存。
  • 对象的生命周期超出作用域:如果对象的生命周期需要超出创建它的函数的作用域,例如,需要在函数中创建一个对象,并在函数返回后继续使用它,那么就需要使用
    new
    来分配内存。
  • 需要管理大量对象:如果需要管理大量的对象,并且这些对象的生命周期各不相同,那么使用
    new
    delete
    可以更灵活地控制内存的使用。

但也要注意,过度使用

new
delete
可能会导致内存泄漏和碎片化,增加程序的复杂性。在可能的情况下,尽量使用智能指针(如
std::unique_ptr
std::shared_ptr
)来自动管理内存,避免手动
new
delete

内存泄漏了怎么办?

内存泄漏是指程序中分配的内存没有被及时释放,导致内存占用越来越高。这是C++程序中常见的问题,也是最难调试的问题之一。

常见的内存泄漏原因包括:

  • 忘记
    delete
    :这是最常见的原因,分配了内存,但是忘记了释放。
  • 异常安全问题:如果在
    new
    delete
    之间抛出了异常,可能会导致
    delete
    没有被执行。
  • 循环引用:在使用智能指针时,如果存在循环引用,可能会导致对象无法被释放。

检测内存泄漏的工具很多,比如Valgrind(Linux)、Visual Studio的内存诊断工具(Windows)等。这些工具可以帮助你找到内存泄漏的位置,并分析泄漏的原因。

预防内存泄漏的最佳方法是:

  • 使用智能指针:尽可能使用智能指针来自动管理内存。
  • 养成良好的编程习惯:在分配内存后,立即编写释放内存的代码,并确保在所有可能的执行路径上都能正确释放内存。
  • 使用内存泄漏检测工具:定期使用内存泄漏检测工具来检查程序是否存在内存泄漏。

总而言之,

new
delete
是C++中动态内存管理的重要工具,理解它们的工作原理,掌握正确的使用方法,才能编写出高效、稳定的C++程序。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

401

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

620

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

354

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

259

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

607

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

531

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

647

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

604

2023.09.22

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 8万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

C++教程
C++教程

共115课时 | 14.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号