new/delete和malloc/free到底有什么区别

new和malloc

文章目录

  • new和malloc
  • 前言
  • 一、属性上的区别
  • 二、使用上的区别
  • 三、内存位置的区别
  • 四、返回类型的区别
  • 五、分配失败的区别
  • 六、扩张内存的区别
  • 七、系统调度过程的区别
  • 总结


前言

new和malloc的知识点,作为一个嵌入式工程师是必须要了解清楚的。new和malloc的区别到底在哪里呢

内存分配通常在以下场景下使用:

动态数据结构:如链表、栈、队列和图,这些数据结构的大小在程序运行时可能会变化。
大数据处理:当需要处理大块数据(如图像、文件数据等)时,动态分配可以根据实际需求分配内存。
用户输入:当用户输入的内容大小不可预见时,如读取不定长度的字符串。
资源管理:在需要创建大量对象,但具体数量在编译时无法确定的情况,如对象池或缓存系统。
动态内存分配提供了灵活性,使程序能够有效地管理内存,根据实际需求分配和释放内存。

一、属性上的区别

new/delete:是C++中的关键字(操作符),若要使用,需要编译器支持;
malloc/free:是标准库函数,若要使用则需要引入相应的头文件才可以正常使用。

二、使用上的区别

malloc:申请空间需要显式填入申请内存的大小;
new:无需显式填入申请的内存大小,new会根据new的类型分配内存。

/** malloc/free **/
int  *a  = (int*) malloc(4)free(a)

在这里,malloc(4) 分配了 4 字节的内存。由于 int 类型通常占用 4 字节,因此分配了足够存储一个 int 类型的数据。free 函数用于释放之前通过 malloc 或其他动态内存分配函数分配的内存。在这里,free(a) 释放了指针 a 指向的 4 字节的内存块。

#include <stdio.h>
#include <stdlib.h>int main() {// 动态分配内存以存储一个整数int *a = (int*) malloc(sizeof(int));// 检查内存分配是否成功if (a == NULL) {printf("内存分配失败\n");return 1; // 结束程序并返回错误代码}// 设置分配的内存中的值*a = 42;// 打印内存中的值printf("内存中的值是: %d\n", *a);// 释放分配的内存free(a);// 将指针设为 NULL,避免悬挂指针a = NULL;return 0;
}

在这里插入图片描述
在调用 free 函数之前,确保指针确实指向了动态分配的内存是非常重要的。
为什么需要确保指针指向动态分配的内存?
1.内存释放的正确性:
free 函数的作用是释放之前由 malloc、calloc 或 realloc 函数分配的内存。如果指针 a 不指向有效的动态分配内存区域(即没有通过这些函数分配的内存),调用 free(a) 可能会导致未定义行为。未定义行为可能会导致程序崩溃、内存泄漏、数据损坏或其他难以预测的错误。
2.内存管理的安全性:
如果 a 指向非动态分配的内存(比如一个局部变量、全局变量或者静态变量),调用 free 可能会导致操作系统试图释放不属于它的内存,造成错误。例如,如果你试图释放一个未分配的指针或者已经被释放的指针(悬挂指针),这也会导致问题。
确保指针指向动态内存的措施
1.初始化指针:
在使用指针之前,初始化它为 NULL。这样,如果你忘记分配内存,它至少不会指向一个不确定的位置。
例如:int *a = NULL;
分配内存之后检查指针:
每次调用 malloc 或相关函数后,都应该检查指针是否为 NULL。如果为 NULL,说明内存分配失2.败,需要处理这种情况。
2.避免重复释放
确保每个动态分配的内存块只被释放一次。重复释放同一块内存会导致未定义行为。
在释放内存后,可以将指针设置为 NULL,这有助于避免对已经释放内存的重复释放尝试。

free(a);
a = NULL;

3.管理指针的生命周期:
确保在释放内存之前,所有指针操作都合法且在范围内。避免在释放内存后还尝试使用该内存(如访问已释放的内存)。

 // 尝试释放已经释放的指针,安全地检查if (a != NULL) {free(a); // 这行不会被执行,因为 ma 是 NULL}
/** new/delete **/
int *b = new int(0);

分配内存:使用 new 关键字在堆上分配内存来存储一个 int 类型的值。
初始化内存:将这个 int 初始化为 0。
返回指针:new 操作符返回一个指向这块内存的指针,该指针被赋值给 b。
因此,b 是一个指向 int 类型的指针,指向的内存位置存储着值 0。

#include <iostream>int main() {// 使用 new 操作符分配内存并初始化为 0int *b = new int(0);// 输出指针 b 指向的值std::cout << "The value of *b is: " << *b << std::endl;// 修改 b 指向的值*b = 42;std::cout << "The new value of *b is: " << *b << std::endl;// 释放分配的内存 避免内存泄漏delete b;// 将 b 设置为 nullptr,以避免悬挂指针b = nullptr;return 0;
}

在这里插入图片描述

三、内存位置的区别

new:此操作符分配的内存空间是在自由存储区;
malloc:申请的内存是在堆空间。
C/C++的内存通常分为:堆、栈、自由存储区、全局/静态存储区、常量存储区。可能除了自由存储区,其他的内存分布大家应该都比较熟悉。堆:是C语言和操作系统的术语,堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,调用free()归还内存。自由存储区:是C++中动态分配和释放对象的一个概念,通过new分配的内存区域可以称为自由存储区,通过delete释放归还内存。自由存储区可以是堆、全局/静态存储区等,具体是在哪个区,主要还是要看new的实现以及C++编译器默认new申请的内存是在哪里。但是基本上,很多C++编译器默认使用堆来实现自由存储,运算符new和delete内部默认是使用malloc和free的方式来被实现,说它在堆上也对,说它在自由存储区上也正确。因为在C++中new和delete符号是可以重载的,我们可以重新实现new的实现代码,可以让其分配的内存位置在静态存储区等。而malloc和free是C里的库函数,无法对其进行重载。

四、返回类型的区别

new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。
malloc内存分配成功则是返回void* ,需要通过强制类型转换将void*指针转换成我们需要的类型。所以在C++程序中使用new会比malloc安全可靠。

五、分配失败的区别

malloc分配内存失败时返回NULL,我们可以通过判断返回值可以得知是否分配成功;
new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL,分配失败时如果不捕捉异常,那么程序就会异常退出。

六、扩张内存的区别

malloc:使用malloc分配内存后,发现内存不够用,那我们可以通过realloc函数来扩张内存大小,realloc会先判断当前申请的内存后面是否还有足够的内存空间进行扩张,如果有足够的空间,那么就会往后面继续申请空间,并返回原来的地址指针;否则realloc会在另外有足够大小的内存申请一块空间,并将当前内存空间里的内容拷贝到新的内存空间里,最后返回新的地址指针。
new:new没有扩张内存的机制。

七、系统调度过程的区别

malloc free是库函数而不是运算符,不在编译器控制范围之内,不能够自动调用构造函数和析构函数。NEW在为对象申请分配内存空间时,可以自动调用构造函数,同时也可以完成对对象的初始化。同理,delete也可以自动调用析构函数。而malloc只是做一件事,只是为变量分配了内存,同理,free也只是释放变量的内存。

总结

new:

int *p = new int(5); // 分配内存并初始化为 5

在 C++ 中使用。
会调用构造函数来初始化对象。
用于分配单个对象或数组。
malloc:

int *p = (int*)malloc(sizeof(int)); // 分配内存,但不初始化

在 C 和 C++ 中使用。
不会调用构造函数,内存中的内容是未定义的。
需要强制转换为目标类型。

  1. 内存释放
    new:使用 delete 或 delete[] 来释放内存。
delete p;       // 对应单个对象
delete[] p;     // 对应对象数组

malloc:使用 free 来释放内存。

free(p);
  1. 异常处理
    new:
    如果内存分配失败,new 会抛出 std::bad_alloc 异常。
    可以使用 new(std::nothrow) 来避免抛出异常,而是返回 nullptr。
    malloc:
    如果内存分配失败,malloc 返回 NULL。不会抛出异常,适用于不支持 C++ 异常的环境。
  2. 适用场景
    new:
    适用于 C++ 编程,特别是当你需要初始化对象或管理对象生命周期时。
    与 C++ 的对象构造和析构机制兼容。
    malloc:
    适用于 C 或者 C++ 中的低级内存管理,尤其是当你在 C++ 环境中需要兼容 C 代码时。
    更适合需要原始内存块的场景,但需要手动处理初始化和类型转换。

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

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

相关文章

dedecms——四种webshell姿势

姿势一&#xff1a;通过文件管理器上传WebShell 步骤一&#xff1a;访问目标靶场其思路为 dedecms 后台可以直接上传任意文件&#xff0c;可以通过文件管理器上传php文件获取webshell 步骤二&#xff1a;登陆到后台点击【核心】--》 【文件式管理器】--》 【文件上传】将准备好…

47.面向对象综合训练-汽车

//题目需求&#xff1a;定义数组存储3个汽车对象 //汽车的属性&#xff1a;品牌&#xff0c;价格&#xff0c;颜色 //创建三个汽车对象&#xff0c;数据通过键盘录入而来&#xff0c;并把数据存入到数组当中 1.标准的JavaBean类 public class Car {private String brand;//品…

渗透测试入门学习——php与mysql数据库连接、使用session完成简单的用户注册、登录

关于cookie、session和sessionid&#xff1a; cookie是保存在用户浏览器的令牌&#xff0c;在用户访问网站时&#xff0c;网站可取出用户cookie中存放的内容来识别用户身份&#xff0c;用于会话的sessionid就存放其中 session是用户访问网站时&#xff0c;网站服务器为用户生…

Ubuntu 24.04中安装virtualenv

在Ubuntu 24.04中安装virtualenv&#xff0c;可以按照以下步骤进行&#xff1a; 1. 确保Python已安装‌&#xff1a; 在终端中输入python --version或python3 --version来检查Python的安装情况。 python3 --version2. 安装pip‌&#xff08;如果尚未安装&#xff09;&#x…

第159天:安全开发-Python-协议库爆破FTPSSHRedisSMTPMYSQL等

案例一: Python-文件传输爆破-ftplib 库操作 ftp 协议 开一个ftp 利用ftp正确登录与失败登录都会有不同的回显 使用ftplib库进行测试 from ftplib import FTP # FTP服务器地址 ftp_server 192.168.172.132 # FTP服务器端口&#xff08;默认为21&#xff09; ftp_po…

【Linux取经之路】Linux项目自动化构建工具-make/makefile git三板斧

目录 关于make和makefile 一个案例 make和makefile的使用 makefile的基本语法 git的使用 关于make和makefile make是 Linux 系统中广泛使用的一个自动化构建工具&#xff0c;它根据用户定义的规则&#xff08;通常保存在一个名为 makefile的文件中&#xff09;来自动编译…

Maya---机械模型制作

材质效果&#xff08;4&#xff09;_哔哩哔哩_bilibili 三角面 四边面 多边面 *游戏允许出现三角面和四边面 游戏中一般是低模&#xff08;几千个面&#xff09; 动漫及影视是高模 机械由单独零件组合而成&#xff0c;需独立制作 低面模型到高面模型 卡线是为了将模型保…

UE5学习笔记22-武器瞄准和武器自动开火

0、一些疑问的记录 1.UUserWidget类和AHUD类的区别。两者都是关于界面显示的类。 实践&#xff1a; 想让界面和用户有交互使用UUserWidget&#xff0c;如果不要交互只是显示使用AHUD类&#xff0c;例如使用UUserWidget类制作开始界面&#xff0c;游戏开始&#xff0c;游戏设置&…

深度学习之图像数据集增强(Data Augmentation)

文章目录 一、 数据增强概述二、python实现传统数据增强参考文献 一、 数据增强概述 数据增强&#xff08;Data Augmentation&#xff09;是一种技术&#xff0c;通过对现有数据进行各种变换和处理来生成新的训练样本&#xff0c;从而增加数据集的多样性和数量。这些变换可以是…

C#使用TCP-S7协议读写西门子PLC(五)-测试程序

上面四篇我们进行封装连接PLC以及读写PLC内存地址表 C#使用TCP-S7协议读写西门子PLC(一)-CSDN博客 C#使用TCP-S7协议读写西门子PLC(二)-CSDN博客 C#使用TCP-S7协议读写西门子PLC(三)-CSDN博客 C#使用TCP-S7协议读写西门子PLC(四)-CSDN博客 这里我们进行测试操作 西门子PLC-…

[JAVA]介绍怎样在Java中通过字节字符流实现文件读取与写入

一&#xff0c;初识File类及其常用方法 File类是java.io包下代表与平台无关的文件和目录&#xff0c;程序中操作文件和目录&#xff0c;都可以通过File类来完成。 通过这个File对象&#xff0c;可以进行一系列与文件相关的操作&#xff0c;比如判断文件是否存在&#xff0c;获…

floodfill+DFS(2)

文章目录 太平洋大西洋流水问题扫雷游戏迷路的机器人 太平洋大西洋流水问题 class Solution { public:vector<vector<int>> res;int m 0, n 0;vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {m heights.size…

珠宝首饰检测系统源码分享

珠宝首饰检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

在 Python 中使用 JSON

了解如何在 Python 中使用 JSON&#xff0c;从基础到高级技术。本指南涵盖解析、序列化、API 集成和最佳实践。 1. JSON 简介 1.1. 什么是 JSON&#xff1f; JSON&#xff08;JavaScript 对象表示法&#xff09;是一种轻量级数据交换格式&#xff0c;人类可以轻松读取和写入…

mongoDB-1

文章目录 一、疑似坑1.11.2 mongo ops manager1.3 mongo features视图固定大小集合&#xff08;有点类似ringbuffer数据结构&#xff0c;capped collections&#xff09;(聚簇集合)clustered collection(类比到Mysql的聚簇索引)聚合管道 aggregation pipelineWiredTiger (默认存…

uniapp微信小程序用户授权方法

效果 步骤 1&#xff09;div标签 <button type"primary" class"btn-login" click"getUserInfo">一键登录</button>2&#xff09;js方法 methods: {getUserInfo() {console.log("aaaa")uni.getUserProfile({desc: Wexin, …

iPhone 上丢失了重要的联系人?如何恢复已删除的 iPhone 联系人

丢失 iPhone 上的联系人可能会带来灾难。无论是一份很棒的新工作机会、潜在的恋爱对象&#xff0c;还是您一直想打电话的老朋友&#xff0c;如果您打开“联系人”应用时看到空白&#xff0c;这绝不是好事。不过&#xff0c;一切并非全无&#xff0c;仍然可以通过备份或专业软件…

Mamba对UNet王炸升级!全新混合架构参数小了116倍,精度依旧完成超车

UNet又升级了&#xff01;北大最新提出LightM-UNet&#xff0c;用Mamba设计1.8M参数UNet&#xff0c;比nnU-Net小了116倍&#xff0c;计算量减少21倍&#xff0c;精度依然SOTA&#xff01; 这种将Mamba与UNet结合的策略利用了两者在图像处理和网络架构上的优势&#xff0c;既能…

Renesas R7FA8D1BH (Cortex®-M85)控制SHT20

目录 概述 1 硬件接口介绍 2 SHT20模块 2.1 SHT20简介 2.2 SHT-20模块电路 3 I2C接口实现 3.1 FSP配置I2C 3.2 I2C驱动程序实现 4 SHT20驱动程序 4.1 SHT20驱动代码结构 4.2 源代码文件 5 测试 5.1 测试功能介绍 5.2 测试代码实现 5.3 运行代码 概述 本文主要介…

持续集成与持续交付CI/CD

CI/CD 是指持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;或持续交付&#xff08;Continuous Delivery&#xff09; 持续集成&#xff08;Continuous Integration&#xff09; 持续集成是一种软件开发实践&…