【C/C++ new/delete和malloc/free的异同及原理】

new/delete和malloc/free都是用于在C++(以及C语言在malloc/free的情况下)中动态申请和释放内存的机制,但它们之间存在一些显著的异同点。以下是对这两组函数/运算符的异同点的详细分析:

相同点

  1. 目的相同:两者都用于在堆(heap)上动态地分配和释放内存。
  2. 手动管理:无论是new/delete还是malloc/free,都需要程序员手动进行内存的分配和释放,以避免内存泄漏。

不同点

  1. 类型与来源
    new/delete:是C++的运算符,支持重载,可以与C++的类特性(如构造函数、析构函数)紧密集成。
    malloc/free:是C语言(及C++兼容)的标准库函数,分别定义在<stdlib.h>(C语言)和(C++)头文件中。
  2. 内存分配与初始化
    new:能够自动根据对象的类型计算所需内存大小,并在分配内存后自动调用对象的构造函数进行初始化(如果是类类型的对象)。
    malloc:需要程序员手动计算所需内存大小,并且分配的内存不会自动初始化,通常包含未定义的值。
  3. 返回值
    new:返回指向分配的内存的指针,该指针的类型是所分配对象的类型。
    malloc:返回void*类型的指针,指向分配的内存,需要程序员根据需要进行类型转换。
  4. 错误处理
    new:如果内存分配失败,会抛出std::bad_alloc异常。
    malloc:如果内存分配失败,会返回NULL(在C++11及以后,推荐使用nullptr)。
  5. 内存释放
    delete:在释放内存时,会调用对象的析构函数(如果是类类型的对象),然后释放内存。
    free:仅释放之前通过malloc分配的内存,不会调用任何析构函数。
  6. 数组支持
    new/delete:对于数组,有专门的语法new 类型[大小]和delete[] 指针来分配和释放内存。
    malloc/free:对于数组,只需在malloc中指定数组总大小(每个元素的类型大小乘以元素数量),并在free中传递指向数组首元素的指针。但注意,malloc不会自动处理数组元素的构造或析构。
  7. 类型安全
    new:提供了更好的类型安全,因为返回的是具体类型的指针,编译器可以进行类型检查。
    malloc:由于返回void*类型,需要程序员进行类型转换,这可能引入类型错误。
  8. 性能
    在底层实现上,new/delete通常是对malloc/free的封装,因此它们的性能差异主要取决于封装层的开销。在大多数情况下,这种差异可以忽略不计,但在性能敏感的应用中可能需要考虑。
现在开始添加阿秀总结部分(很清晰、易懂,非常建议学习
  1. new是类型安全的,malloc不是。例如:

    int*p=newfloat[2];//编译错误
    int *p = (int*)malloc(2*sizeof(double));//编译无错误
    
  2. new调用名为operator new的标准库函数分配足够空间并调用相关对象的构构造函数,delete对指针所指对象运行适当的析构函数,然后通过调用名为perator delete的标准库函数释放该对象所用内存。后者均没有相关调用。

  3. new是封装了malloc,直接free不会报错,但是这只是释放内存,而不会析构对象

  4. new和delete是如何实现的?
    new的实现过程是:首先调用名为operator new的标准库函数,分配足够大的原始为类型化的内存,以保存指定类型的一个对象;接下来运行该类型的一个构造函数,用指定初始化构造对象;最后返回指向新分配并构造后的的对象的指针;
    delete的实现过程:对指针指向的对象运行适当的析构函数;然后通过调用名为operator delete的标准库函数释放该对象所用内存;

  5. malloc和new的区别?
    malloc和free是标准库函数,支持覆盖;new和delete是运算符,支持重载。
    malloc仅仅分配内存空间,free仅仅回收空间,不具备调用构造函数和析构函数功能,用malloc分配空间存储类的对象存在风险;new和delete除了分配回收功能外,还会调用构造函数和析构函数。
    malloc和free返回的是void类型指针(必须进行类型转换),new和delete返回的是具体类型指针。

  6. 既然有了malloc/free,C++中为什么还需要new/delete呢?直接用malloc/free不好吗?
    malloc/free和new/delete都是用来申请内存和回收内存的。
    在对非基本数据类型的对象使用的时候,对象创建的时候还需要执行构造函数,销毁的时候要执行析构函数。而malloc/free是库函数,是已经编译的代码,所以不能把构造函数和析构函数的功能强加给malloc/free,所以new/delete是必不不可少的。

  7. 被free回收的内存是立即返还给操作系统吗?
    不是的,被free回收的内存会首先被ptmalloc使用双链表保存起来,当用户下一次申请内存的时候,会尝试从这些内存中寻找合适的返回。这样就避免了频繁的系统调用,占用过多的系统资源。同时ptmalloc也会尝试对小块内存进行合并,避免过多的内存碎片。

总结

new/delete和malloc/free各有其适用场景。在C++程序中,由于new/delete能够与C++的类特性更好地集成,因此通常是首选的内存分配方式。然而,在处理与C语言的接口或需要更低级内存操作的情况下,malloc/free仍然有其不可替代的作用。重要的是,无论使用哪种方式,都应确保及时释放分配的内存,以避免内存泄漏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/39623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++编程逻辑讲解step by step:类之间的交互

题目 设计一个点类Point&#xff0c;再设计一个矩形类&#xff0c;矩形类使用Point类的两个坐标点作为矩形的对角顶点。并可以输出4个坐标值和面积。 分析 1.点类&#xff0c;自然维护的是一个点的坐标&#xff0c; #include < iostream > using namespace std; class …

【C语言基础知识点】C语言-使用 fgets 读取包含空格的字符串

使用 fgets 读取包含空格的字符串 // 使用 fgets 读取包含空格的字符串 #include <stdio.h> #include <string.h> int main() { char name[100]; printf("Enter your name: "); fgets(name, sizeof(name), stdin); // 移除可能读取到的换行符 n…

Matlab/simulink三段式电流保护

电流1段仿真波形如下所示 电流2段仿真波形如下所示 电流3段仿真波形如下所示

Centos7安装Minio笔记

一、Minio概述 Minio是一款开源的对象存储服务器&#xff0c;可以运行在多种操作系统上&#xff0c;包括Linux、Windows和MacOS等。提供一种简单、可扩展、高可用的对象存储解决方案&#xff0c;支持多种数据格式&#xff0c;包括对象、块和文件等。Minio是一款强大、灵活、可…

WCCI 2024第三弹:忍者表演惊艳全场,盛大晚宴不容错过

WCCI 2024第三弹&#xff1a;忍者表演惊艳全场&#xff0c;盛大晚宴不容错过&#xff01; 会议之眼 快讯 会议介绍 IEEE WCCI&#xff08;World Congress on Computational Intelligence&#xff09;2024&#xff0c;即2024年IEEE世界计算智能大会&#xff0c;于6月30日至7月…

【前端知识】一篇速成 建议收藏

HTML基础概念 正式敲代码之前呢,我们先来看几个概念: 0 静态网页和动态网页 静态网页: 页面的内容和显示效果就基本上不会发生变化了--除非你修改页面代码。 动态网页: 页面代码虽然没有变&#xff0c;但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的…

【康复学习--LeetCode每日一题】3099. 哈沙德数

题目&#xff1a; 如果一个整数能够被其各个数位上的数字之和整除&#xff0c;则称之为 哈沙德数&#xff08;Harshad number&#xff09;。给你一个整数 x 。如果 x 是 哈沙德数 &#xff0c;则返回 x 各个数位上的数字之和&#xff0c;否则&#xff0c;返回 -1 。 示例 1&a…

【Qt知识】window frame 对窗口坐标的影响

在Qt中&#xff0c;窗口框架&#xff08;Window Frame&#xff09;对Widget的尺寸计算和坐标定位有着直接的影响&#xff0c;这主要是因为窗口框架本身占据了一定的空间&#xff0c;包括标题栏、最小化/最大化/关闭按钮以及边框。这部分额外的空间在不同的应用场景下需要被考虑…

windows非白名单exe监控并杀死

需求&#xff1a;孩子在家用电脑上网课&#xff0c;总是悄悄打开游戏或视频软件 方案&#xff1a;指定白名单exe&#xff0c;打开非白名单的就自动被杀死&#xff0c;并记录日志供查看 不知道是否还有更好的结果方案&#xff1f; import psutil import time import logging#…

2024.7.4 刷题总结

2024.7.4 **每日一题** 3086.拾起k个1需要的最少行动次数&#xff0c;在这道题我们可以把0看成空位&#xff0c;第二种操作相当于把一个1移动到和它相邻的空位上&#xff0c;而第一种操作则是贪心地把和当前下标相邻的0变成1;当maxchanges较大时&#xff0c;优先使用第一种操作…

第二十条:与抽象类相比,优先选择接口

要定义多种实现的类型&#xff1a;JAVA有两种机制&#xff1a;接口和抽象类。这两种机制都支持为某些实例方法提供实现&#xff0c;但二者有个重要的区别&#xff1a;要实现由抽象类定义的类型&#xff0c;这个类必须是抽象类的子类。因为Java只允许单继承&#xff0c;对抽象类…

使用SSE实现echarts数据实时更新

区别 SSE 和 WebSocket 原理和实现方式的区别 SSE( Server-Sent Events) SSE 是基于传统的 HTTP 协议实现的&#xff0c;采用了长轮询&#xff08;long-polling&#xff09;机制。客户端通过向服务器发送一个 HTTP 请求&#xff0c;服务器保持连接打开并周期性地向客户端发送…

内网穿透--利用everything实现目录映射

免责声明:本文仅做技术交流与学习... 目录 来源文章 frp下载网址 为了隐藏: 演示: 1-靶机的everything开启http服务 2-Linux服务器: 3-靶机windows: 4-最后访问: 来源文章 渗透测试技巧|Everything的利用 frp下载网址 Release v0.58.1 fatedier/frp GitHub 为了隐…

协程调度模块

什么是协程和协程调度&#xff1f; 基本概念 协程 协程是一种比线程更轻量级的并发编程结构&#xff0c;它允许在函数执行过程中暂停和恢复执行状态&#xff0c;从而实现非阻塞式编程。协程又被称为用户级线程&#xff0c;这是由于协程包括上下文切换在内的全部执行逻辑都是…

WAIC热点聚焦|具身智能简介:AI新浪潮的领跑者

WAIC热点聚焦|具身智能简介&#xff1a;AI新浪潮的领跑者 引言 随着"具身智能"&#xff08;Embodied Intelligence&#xff09;的火热讨论&#xff0c;2024年标志着人机交互新时代的开启。在大模型技术的推动下&#xff0c;机器人响应语音指令成为现实&#xff0c;…

Linux Rsyslog+LogAnalyzer+MariaDB部署日志服务器

文章目录 Linux RsyslogLogAnalyzerMariaDB部署日志服务器1 环境准备1.1 服务器端安装LAMP环境1.2 服务启动并加入开机启动1.2.1 Apache1.2.2 MariaDB1.2.3 Php 2 Rsyslog服务端安装及配置2.1 安装Rsyslog及Rsyslog连接MySQL的模块2.2 导入rsyslog-mysql数据库文件2.3 查看刚导…

深入浅出:npm常用命令详解与实战

theme: smartblue npm是什么 npm&#xff08;Node Package Manager&#xff09;是Node.js平台的默认包管理器&#xff0c;它让JavaScript开发者能够轻松地共享、管理和使用彼此编写的代码模块。npm不仅仅是一个安装工具&#xff0c;它还是一个全面的生态系统&#xff0c;用于发…

【YOLOv5/v7改进系列】替换损失函数为WIOU、CIOU、GIOU、SIOU、DIOU、EIOU、Focal C/G/S/D/EIOU等

一、导言 在目标检测任务中&#xff0c;损失函数的主要作用是衡量模型预测的边界框&#xff08;bounding boxes&#xff09;与真实边界框之间的匹配程度&#xff0c;并指导模型学习如何更精确地定位和分类目标。损失函数通常由两部分构成&#xff1a;分类损失&#xff08;用于…

RabbitMQ入门教程(精细版二带图)

目录 六 RabbitMQ工作模式 6.1Hello World简单模式 6.1.1 什么是简单模式 6.1.2 RabbitMQ管理界面操作 6.1.3 生产者代码 6.1.4 消费者代码 6.2 Work queues工作队列模式 6.2.1 什么是工作队列模式 6.2.2 RabbitMQ管理界面操作 6.2.3 生产者代码 6.2.4 消费者代码 …

清理测试数据用truncate还是delete

truncate和delete的区别&#xff0c;我相信大家都清楚。 truncate会清空表的全部数据&#xff0c;且自增主键会重置&#xff1b;而delete可以按条件删除&#xff0c;且自增主键不会重置。 我们日常测试过程中经常要删除掉测试数据&#xff0c;那么应该用truncate删&#xff0c…