C++ new 和 malloc 的区别?

 

相关系列文章

C++ new 和 malloc 的区别?

C++内存分配策略​​​​​​​

目录

1.引言

2.区别

2.1.申请的内存分配区域

2.2.类型安全和自动大小计算

2.3.构造函数和析构函数的调用

2.4.异常处理

2.5.配对简便性

2.6.new 的重载

2.7.关键字和操作符

3.总结


1.引言

new 和 delete 在 C++ 中被引入,主要是为了解决 malloc 和 free 在 C 语言中的一些限制和问题,特别是在面向对象编程方面。以下是 new/delete 相比于 malloc/free 的主要区别。

2.区别

2.1.申请的内存分配区域

        new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。

        那么自由存储区是否能够是堆(问题等价于new是否能在堆上动态分配内存),这取决于operator new 的实现细节。自由存储区不仅可以是堆,还可以是静态存储区,这都看operator new在哪里为对象分配内存。

        特别的,new甚至可以不为对象分配内存!定位new的功能可以办到这一点:

new (place_address) type

        place_address为一个指针,代表一块内存的地址。当使用上面这种仅以一个地址调用new操作符时,new操作符调用特殊的operator new,也就是下面这个版本:

void * operator new (size_t,void *) 
//不允许重定义这个版本的operator new

        这个operator new不分配任何的内存,它只是简单地返回指针实参,然后右new表达式负责在place_address指定的地址进行对象的初始化工作。

2.2.类型安全和自动大小计算

malloc/free 示例:

#include <stdlib.h>struct MyStruct {int data;// ... 其他成员 ...
};int main() {// 使用 malloc 分配内存,需要手动计算大小MyStruct* p = (MyStruct*)malloc(sizeof(MyStruct));p->data = 10;free(p);return 0;
}

new/delete 示例:

struct MyStruct {int data;// ... 其他成员 ...
};int main() {// 使用 new 分配内存,自动处理大小和类型MyStruct* p = new MyStruct;p->data = 10;delete p;return 0;
}

区别:

  • new 自动计算所需内存的大小,而 malloc 需要程序员手动计算。

  • new 提供类型安全,返回正确类型的指针,避免了强制类型转换的需要。

2.3.构造函数和析构函数的调用

使用new操作符来分配对象内存时会经历三个步骤:
        1)调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。
        2)编译器运行相应的构造函数以构造对象,并为其传入初值。
        3)对象构造完成后,返回一个指向该对象的指针。
 使用delete操作符来释放对象内存时会经历两个步骤:
        1)调用对象的析构函数。
        2)编译器调用operator delete(或operator delete[])函数释放内存空间。
        总之来说,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会。下面看个示例:

class MyClass {
public:MyClass() { std::cout << "Constructor called\n"; }~MyClass() { std::cout << "Destructor called\n"; }
};int main() {MyClass* obj = new MyClass; // 调用构造函数delete obj;                 // 调用析构函数return 0;
}

区别:

  • new 在分配内存时调用对象的构造函数,delete 在释放内存时调用析构函数。

  • malloc 和 free 只处理内存分配和释放,不调用构造函数和析构函数。

2.4.异常处理

        new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。示例如下:

int main() {try {int* p = new int[10000000000]; // 尝试分配大量内存} catch (const std::bad_alloc& e) {std::cerr << "Memory allocation failed: " << e.what() << '\n';}return 0;
}

区别:

  • new 在内存分配失败时抛出异常(如 std::bad_alloc),而 malloc 在失败时返回 NULL

  • 这使得 new 能够更好地集成到 C++ 的异常处理框架中。

2.5.配对简便性

  • new 和 delete 是为对象配对的,而 malloc 和 free 需要显式计算大小。

如:

//[1]
A * ptr = new A[10];//分配10个A对象
delete []ptr;//[2]
int * ptr = (int *) malloc( sizeof(int)* 10 );
//分配一个10个int元素的数组
free(ptr);
  • new[] 和 delete[] 用于数组,简化了数组内存管理。

new对数组的支持体现在它会分别调用构造函数函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。注意delete[]要与new[]配套使用,不然会找出数组对象部分释放的现象,造成内存泄漏

2.6.new 的重载

是的,C++ 允许重载 new 操作符。这意味着你可以定义自己的 new 操作符来改变对象的分配方式。重载 new 可以用于自定义内存管理,追踪内存分配,或者引入特殊的内存分配策略。标准库是定义了operator new函数和operator delete函数的8个重载版本:

//这些版本可能抛出异常
void * operator new(size_t);
void * operator new[](size_t);
void * operator delete (void * )noexcept;
void * operator delete[](void *0)noexcept;
//这些版本承诺不抛出异常
void * operator new(size_t ,nothrow_t&) noexcept;
void * operator new[](size_t, nothrow_t& );
void * operator delete (void *,nothrow_t& )noexcept;
void * operator delete[](void *0,nothrow_t& )noexcept;

         我们可以自定义上面函数版本中的任意一个,前提是自定义版本必须位于全局作用域或者类作用域中。

        重载 new 需要提供与系统 new 相同的返回类型和参数列表。最常见的形式是重载全局 new 和 delete

void* operator new(std::size_t size) {std::cout << "Custom new for size " << size << std::endl;return std::malloc(size);
}void operator delete(void* memory) {std::cout << "Custom delete" << std::endl;std::free(memory);
}

类也可以重载其自身的 new 和 delete,这对于控制特定类的对象分配非常有用。

class MyClass {
public:void* operator new(std::size_t size) {std::cout << "MyClass new" << std::endl;return std::malloc(size);}void operator delete(void* memory) {std::cout << "MyClass delete" << std::endl;std::free(memory);}
};

2.7.关键字和操作符

new 是操作符,malloc 是函数。

关键字(Keywords)和操作符(Operators)在编程语言中是两个不同的概念:

  • 关键字:这些是编程语言预定义的保留字,每个关键字有特定的含义,并在语言的语法中扮演特定的角色。例如,ifwhilereturn 等在 C++ 中都是关键字。关键字不能用作变量名或函数名。

  • 操作符:操作符用于执行操作,如算术运算、逻辑运算、比较等。在 C++ 中,一些操作符可以被重载,这意味着你可以改变它们的行为以适应特定类型的操作。例如,+-*/new 等都是操作符。

有些情况下,某些关键字也可以被视为操作符。例如,new 和 delete 在 C++ 中既是关键字也是操作符。它们作为关键字,表示特定的动作(分配和释放内存),同时它们的行为可以像操作符那样被重载。

3.总结

new/delete 提供了更符合 C++ 面向对象特性的内存管理方式。它们处理类型安全、对象生命周期(构造和析构)、异常安全以及简化语法。然而,这些改进也带来了一定的性能开销,这在某些性能敏感的应用中可能是一个考虑因素。在 C++ 中,new/delete 是推荐的方式,因为它们提供了更安全和便利的内存管理机制。

C++内存分配策略-CSDN博客

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

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

相关文章

HACKTHEBOX通关笔记——mango(退役)

信息收集 端口扫描 ┌──(root㉿kali)-[~] └─# nmap -sC -sV -A -p- --min-rate10000 10.129.229.185 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-31 20:44 EST Warning: 10.129.229.185 giving up on port because retransmission cap hit (10). Nmap scan …

【微服务】skywalking自定义告警规则使用详解

目录 一、前言 二、SkyWalking告警功能介绍 2.1 SkyWalking告警是什么 2.2 为什么需要SkyWalking告警功能 2.2.1 及时发现系统异常 2.2.2 保障和提升系统稳定性 2.2.3 避免数据丢失 2.2.4 提高故障处理效率 三、 SkyWalking告警规则 3.1 SkyWalking告警规则配置 3.2 …

VMware虚拟机网络配置

VMware虚拟机网络配置 桥接模式NAT网络 桥接模式 桥接模式其实就是借助你宿主机上的网卡进行联网和通信&#xff0c;所以相当于虚拟机和宿主机平级&#xff0c;处于同一个网段中。 配置要点&#xff1a; 注意选择正确的宿主机网卡 查看宿主机的网络信息&#xff0c;这些信息指…

[嵌入式AI从0开始到入土]8_在线Gpu环境训练(基于启智ai协作平台)

[嵌入式AI从0开始到入土]嵌入式AI系列教程 注&#xff1a;等我摸完鱼再把链接补上 可以关注我的B站号工具人呵呵的个人空间&#xff0c;后期会考虑出视频教程&#xff0c;务必催更&#xff0c;以防我变身鸽王。 第1期 昇腾Altas 200 DK上手 第2期 下载昇腾案例并运行 第3期 官…

原子变量和原子操作

一、什么是原子操作 通常某一个变量的操作对应的CPU指令是大于一个的&#xff0c;在多线程环境下&#xff0c;为了确保对共享变量的操作在执行时不会被干扰&#xff0c;从而避免竞态条件和死锁等问题&#xff0c;使用原子变量。 原子变量可以看作是一种特殊的类型&#xff0c…

php基础学习之函数

基本概念 是一种语法结构&#xff0c;将实现某一个功能的代码块封装到一个结构中&#xff0c;从而实现代码的重复利用 php函数的定义语法 &#xff08;与C/Java很类似&#xff0c;区别在于没有数据类型&#xff0c;因为php是弱类型语言&#xff09; function 函数名(参数){ //…

会计财税答案怎么查找?推荐你使用这五个公众号和工具 #知识分享#微信

当今社会&#xff0c;随着信息技术的迅猛发展&#xff0c;大学生们在学习过程中面临着各种各样的困难和挑战。而在这些挑战中&#xff0c;面对繁重的作业和复杂的题目&#xff0c;大学生搜题软件应运而生 1.题小聪 这个是公众号 电大国开试题库为主&#xff0c;搜题效率挺高…

Linux 查看 系统基本信息 uname

基本用法&#xff1a; 在终端中输入"uname"即可显示系统的内核名称。 可以结合不同的参数使用&#xff0c;获取更详细的系统信息。 常见参数&#xff1a; “-s”&#xff1a;显示操作系统名称。 “-n”&#xff1a;显示网络节点主机名。 “-r”&#xff1a;显示内核版…

Linux之动静态库

今天我们来讲动静态库&#xff01; 首先我们来粗粒度的划分一下动态库和静态库。 动态库就是只有一份库文件&#xff0c;所有想用该库的文件与改库文件建立链接&#xff0c;然后使用。这样可以提高代码复用率&#xff0c;避免重复拷贝产生没必要的内存消耗。 静态库&#xf…

UART通信中的奇偶校验

UART通信中的奇偶校验&#xff1a;提升数据传输可靠性的简单方法 在微控制器&#xff08;MCU&#xff09;和各种电子设备之间的数据通信领域&#xff0c;UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff0c;通用异步收发传输器&#xff09;协议是一种广泛…

openGauss学习笔记-220 openGauss性能调优-确定性能调优范围-查询最耗性能的SQL

文章目录 openGauss学习笔记-220 openGauss性能调优-确定性能调优范围-查询最耗性能的SQL220.1 操作步骤 openGauss学习笔记-220 openGauss性能调优-确定性能调优范围-查询最耗性能的SQL 系统中有些SQL语句运行了很长时间还没有结束&#xff0c;这些语句会消耗很多的系统性能&…

Django CORS 跨域问题解决

座右铭&#xff1a;怎么简单怎么来&#xff0c;以实现功能为主。 欢迎大家关注公众号与我交流 环境安装 pip install django-cors-headers settings.py 修改配置 INSTALLED_APPS ["","corsheaders", # 加上这个"", ]MIDDLEWARE ["cors…

软件项目版本与文档管理的最佳实践

在软件项目开发过程中&#xff0c;版本管理和项目文档管理是至关重要的一环。它们直接影响到项目的顺利进行和最终成果的质量。然而如何有效地管理和维护这些信息&#xff0c;同时保持独立和客观的态度&#xff0c;是每个开发者都需要掌握的技能。本文将探讨如何在软件开发过程…

HCIA-HarmonyOS设备开发认证V2.0-轻量系统内核基础-消息队列queue

目录 一、消息队列基本概念二、消息队列运行机制三、消息队列开发流程四、消息队列使用说明五、消息队列接口六、代码分析&#xff08;待续...&#xff09;坚持就有收获 一、消息队列基本概念 队列又称消息队列&#xff0c;是一种常用于任务间通信的数据结构。队列接收来自任务…

BossPlayerCTF

靶场环境问题 靶场下载之后&#xff0c;可能会出现扫描不到IP的情况&#xff0c;需要进行调整&#xff0c;参考&#xff1a; Vulnhub靶机检测不到IP地址_vulnhub靶机nmap扫不到-CSDN博客 该靶机没有vim&#xff0c;需要使用vi命令去修改&#xff1b;改成当前网卡即可&#x…

第21讲关于我们页面实现

关于我们页面实现 关于锋哥页面author.vue 我们这里用一个vip宣传页面&#xff0c;套一个web-view <template><web-view src"http://www.java1234.com/vip.html"></web-view> </template><script> </script><style> <…

【Java多线程案例】定时器

1. 定时器简介 定时器&#xff1a;想必大家一定对定时器这个概念不陌生&#xff01;因为它经常出现在我们的日常生活和编程学习中&#xff0c;定时器就好比是一个"闹钟"&#xff0c;会在指定时间处理某件事&#xff08;例如响铃&#xff09;&#xff0c;而在编程世界…

删除 Windows 设备和驱动器中的 WPS网盘、百度网盘等快捷图标

在安装诸如WPS软件、百度云盘、爱奇艺等客户端后&#xff0c;Windows 的“我的电脑”&#xff08;或“此电脑”&#xff09;中的“设备和驱动器”部分会出现对应的软件图标。这种情况被许多技术人员视为不必要的干扰&#xff0c;因此许多用户想要知道如何隐藏或删除这些图标。 …

【初中生讲机器学习】9. 我是怎么用朴素贝叶斯实现垃圾邮件分类的?真的超全!

创建时间&#xff1a;2024-02-14 最后编辑时间&#xff1a;2024-02-15 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…

leetcode刷题之或操作使用场景

文章目录 概要题目问题分析小结 概要 今天晚上上床前刷了一个leetcode的题目&#xff0c;是leetcode的2103题&#xff0c;因为是个简单题&#xff0c;我只是想复习一下hash表的用法。结果反而让我看到了或操作的使用场景。 题目 总计有 n 个环&#xff0c;环的颜色可以是红、…