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

C/C++中的内存管理

C/C++ 中程序使用的内存区域

C中的动态内存管理 

malloc

申请 size 大小的空间

int* pi = (int*)malloc(sizeof(int) * 10);

calloc

申请 num 个 size 大小的空间,
并初始化为 0 值
int* pi = (int*)calloc(10, sizeof(int));

realloc

将 ptr 指向的空间,扩容至 size 大小
int* new_pi = (int*)realloc(pi, sizeof(int)*100);

free

释放掉由 malloc、calloc、
realloc 申请的空间
free(new_pi);

小结

C中的动态内存管理方式,不能很好地支持自定义类型,所以 C++ 中有了 new 和 delete

A* a = (A*)malloc(sizeof(A));	// 为 A 类型申请空间,但不能初始化

C++中的动态内存管理

new & delete

    int* pi = new int;	// 申请 1 个 int 类型的空间int* pi1 = new int(0);	// 初始化为 0int* pi2 = new int[10];	// 申请 10 个 int 类型的空间A* pa = new A;	// 申请 1 个 A 类型的空间,并调用默认构造初始化delete pi;delete pi1;delete[] pi2;delete pa;    // 调用 A 类的析构函数,并释放空间

使用 new 动态申请的内存,必须使用 delete 释放

与 C 中对动态内存管理方式的区别:

对于自定义类型,new 会开空间 + 调用构造函数初始化,delete 会调用析构函数 + 释放空间。

但是对内置类型,处理基本一样,开空间但不会初始化。

另外,new 在申请空间失败后会抛出异常,需用 try catch 捕获;malloc 申请失败后,会返回 NULL

new[ ] & delete[ ]

	A* pa = new A[10];delete[] pa;

new A[n] 和 delete[ ] pa 是对多个对象空间的申请和释放操作,其中,分别调用了 operator new[ ] 与 operator delete[ ] 函数;过程与单个对象空间的申请与释放,基本没有区别。

但是为多个对象开辟和释放空间时,一般 new 会额外开辟空间存取开辟的对象个数(不同编译器的实现方式可能不同),以便 delete 时,编译器知道该释放掉多大空间。

operator new

针对自定义类型,使用 new 创建对象,实际上做了两步操作

(1)调用了底层的 operator new 这个全局函数申请空间

(2)调用该自定义类型的构造函数

如下图(vs中 new 对象,调试时的汇编指令),在整个 new 对象的过程中, call 了两个函数:operator new 和 A 类的默认构造:

借鉴一下C友的源码:

void* __CRTDECL operator new(size_t const size)
{for (;;){if (void* const block = malloc(size))    // 调用了 malloc{return block;}if (_callnewh(size) == 0){if (size == SIZE_MAX){__scrt_throw_std_bad_array_new_length();}else{__scrt_throw_std_bad_alloc();}}// The new handler was successful; try to allocate again...}
}

发现 operator new 函数中,实际调用了 malloc 来申请内存

operator delete

同理,针对自定义类型,C++ 中的 delete 也是分两步走:

(1)调用该类型的析构函数

(2)调用 operator delete 释放申请的空间

void __CRTDECL operator delete(void* const block) noexcept
{#ifdef _DEBUG_free_dbg(block, _UNKNOWN_BLOCK);#elsefree(block);#endif
}

operator delete 的源码中,仍然是调用了 free 来释放内存。

operator new[ ] & operator delete[ ]

同单个对象的空间申请与释放步骤一样,多个对象 new A[ ] 和 delete[ ] p 时:

new A[ ] :调用多次operator new[ ] + 构造函数

delete [ ] p :调用多次析构函数 + operator delete[ ]

小结

new 和 delete、malloc 和 free 匹配使用,否则行为将未定义。

new 和 delete、malloc 和 free 共同点:都是从堆上申请空间,并且需要手动释放。

区别:

1、malloc 和 free 时函数,new 和 delete 是操作符;

2、malloc 申请的空间不会初始化,而 new 可以初始化;

3、malloc 申请空间时,需要手动计算大小并传参;而 new 只需要在后面跟上类型以及对象个数;

4、malloc 的返回值为 void* ,需要强制转换指针;而 new 因为后跟类型的原因,不需要转换指针类型;

5、malloc 申请失败返回 NULL,对 malloc 使用必须加判空语句;而 new 需要捕获异常;

6、针对自定义类型,malloc/free 只能开辟空间,不会调用构造函数和析构函数;而 new/delete 会在申请空间时调用构造函数完成对象的初始化,delete 会在释放空间之前调用析构函数完成空间中的资源清理。

思考:new 和 delete 目的就是在面向对象编程中,支持自定义类型对象的空间申请、初始化以及资源释放。

http://www.lryc.cn/news/597211.html

相关文章:

  • uniapp+vue3小程序点击保存图片、保存二维码
  • 一洽客服系统:小程序接入功能说明
  • 优化:Toc小程序猜你喜欢功能
  • 校园后勤服务平台小程序的设计与实现
  • FastGPT + Kymo:解锁企业专属知识库与智能体开发新体验
  • 【黑马SpringCloud微服务开发与实战】(六)分布式事务
  • Leetcode力扣解题记录--第54题(矩阵螺旋)
  • 算法:数组part01:704. 二分查找 +977.有序数组的平方
  • Java开发岗面试记录合集
  • LLM 中的 温度怎么控制随机性的?
  • AI驱动攻防升级,API安全走到关键档口
  • CentOS 7 Linux 用 yum 安装 Docker,含 Docker 镜像无法拉取问题(即 docker pull 失败)的解决方案
  • 路由器与交换机的区别
  • 数据结构之队列(C语言)
  • 【优选算法-多源 BFS】多源 BFS:解决多个起点的广度优先搜索
  • 【大模型文生图、文生音频实战Demo】基于Spring AI Alibaba和阿里百炼大模型实现文生图、文生视频
  • Android MediaCodec 的使用和源码实现分析
  • 2.1 为什么定义tensor数据结构?
  • 【有趣的跳跃一维数组问题】2022-7-27
  • 彻底掌握双列集合——Map接口以及实现类和常用API及其底层原理
  • 题解:P9468 [EGOI 2023] Candy / 糖果
  • 亚马逊云科技 上海AI研究院 突然解散 | AI早报
  • Taint Bug (污点漏洞):
  • GitHub 趋势日报 (2025年07月22日)
  • Docker 基础概念
  • 解决Node 17+版本与Metro、Webpack等兼容性问题(500)
  • 数据结构自学Day13 -- 快速排序--“分而治之”
  • ITIL 4:云计算与微服务对组织架构的影响
  • kotlin基础【1】
  • android studio(NewsApiDemo)100%kotlin