当前位置: 首页 > 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.dtcms.com/a/294693.html

相关文章:

  • 分布式事务中的2PC和 3PC
  • 无货源电商亚马逊采购指南:硬件隔离与支付风控实操
  • 多模态融合模型迎来新突破!
  • SAP-ABAP:SAP的MB_MIGO_BADI技术架构及增强详解
  • 代码随想录day23回溯算法2
  • 有关Kubernetes技术的学习
  • RDB和AOF的写回策略分别是什么?
  • 超表面设计参数复杂难优化?OAS光学软件专业方案来破局
  • 开源UI生态掘金:从Ant Design二次开发到行业专属组件的技术变现
  • Hexo - 免费搭建个人博客06 - 安装、切换主题Butterfly
  • C# 日期与时间 DateTime 结构和TimeSpan 结构
  • 网安-JWT
  • LLM 中的 温度怎么控制随机性的?
  • Hyperledger Fabric 中的安全性与隐私保护实现指南
  • uni-app动态获取屏幕边界到安全区域距离的完整教程
  • 【Node.js】使用ts-node运行ts文件时报错: TypeError: Unknown file extension “.ts“ for ts 文件
  • PBR策略路由
  • LeetCode二叉树的公共祖先
  • #Linux内存管理# 详细介绍使用mmap函数创立共享文件映射的工作原理
  • 篇四 tcp,udp客户端服务器编程模型
  • [Linux入门] Linux 文件系统与日志分析入门指南
  • 欢迎咨询年度规划2025
  • 第二阶段-第二章—8天Python从入门到精通【itheima】-136节(Python操作MySQL的基础使用)
  • C++ 多态全解析:静态多态与动态多态详解
  • Packmol聚合物通道模型建模方法
  • OpenCV 图像预处理:颜色操作与灰度、二值化处理详解
  • 最长递增子序列(LIS)问题详解
  • 0723 单项链表
  • FreeRTOS学习笔记之调度机制
  • MySQL 8.0 OCP 1Z0-908 题目解析(34)