C++从入门到实战(十二)详细讲解C++如何实现内存管理
C++从入门到实战(十二)详细讲解C++如何实现内存管理
- 前言
- 一、C++内存管理方式
- 1. new/delete操作内置类型
- 2. 异常与内存管理的联系(简单了解)
- 3. new和delete操作自定义类型
- 二、 operator new与operator delete函数(重点)
- 1. new和delete操作符与operator new和operator delete函数的关系
- 2. operator new函数的工作原理
- 3. operator delete函数的工作原理
- 三、 定位new表达式(placement-new) (了解即可)
- 1. 定位 new 表达式的概念
- 2. 定位 new 表达式的使用格式
- 3. 定位 new 表达式的使用场景
- 四、malloc/free和new/delete的区别
- 1. 相同点
- 2. 不同点
- 一个是函数,一个是操作符
- new 会 “初始化”,malloc 不会
- 空间大小:new 自动计算,malloc 要手动算
- new 不用强转,malloc 需要
- 错误处理:malloc 返 NULL,new 抛异常
- 自定义类型:new/delete 会 “照顾” 对象,malloc/free 不会
前言
- 在上一篇博客中,我们探讨了 C/C++ 语言的内存分布模型,并对比了 C 与 C++ 内存管理的核心差异,初步认识了 C++ 中new与delete的基本概念,为理解 C++ 内存管理体系奠定了基础。
- 本文将在此基础上,深入解析 C++ 内存管理的核心机制,从底层原理到实践细节展开系统讲解,帮助读者全面掌握这一重要知识模块。
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482
一、C++内存管理方式
1. new/delete操作内置类型
- 在 C 语言里有它自己的内存管理办法,但用起来比较麻烦,而且有些情况处理不了。
- C++ 为了解决这些问题,引入了new和delete操作符来进行动态内存管理。
#include using namespace std; void Test() { int* ptr4 = new int; // 动态申请一个int类型的空间 int* ptr5 = new int(10); //动态申请一个int类型的空间并初始化为10 int* ptr6 = new int[3]; //动态申请3个int类型的空间 delete ptr4; delete ptr5; //delete ptr6;//错误在 C++ 中,new 和 delete、new[] 和 delete[] 是成对出现的操作符,它们的使用需要遵循特定的配对规则: //如果使用 delete 而非 delete[] 来释放通过 new[] 分配的数组内存,会产生严重的后果: //内存泄漏:delete 只会释放数组首元素的内存,而不会释放数组中其他元素的内存,这就导致了部分内存无法被回收,造成内存泄漏。 //未定义行为:使用 delete 释放数组内存属于未定义行为,这意味着程序可能会出现各种不可预测的问题,比如程序崩溃、数据损坏等 delete[] ptr6; }
- 在 C++ 中,new 和 delete、new[] 和 delete[] 是成对出现的操作符,它们的使用需要遵循特定的配对规则:
- 如果使用 delete 而非 delete[] 来释放通过 new[] 分配的数组内存,会产生严重的后果:例如上面代码中的int* ptr6 = new int[3]与delete ptr6
内存泄漏:delete 只会释放数组首元素的内存,而不会释放数组中其他元素的内存,这就导致了部分内存无法被回收,造成内存泄漏。
未定义行为:使用 delete 释放数组内存属于未定义行为,这意味着程序可能会出现各种不可预测的问题,比如程序崩溃、数据损坏等
2. 异常与内存管理的联系(简单了解)
- 在使用new申请内存时,如果系统没有足够的内存可供分配,就可能会抛出异常。
- 所以在进行内存管理时,要考虑到这种可能出现的异常情况,确保程序的健壮性。
#include using namespace std; void Test() { try { // 动态申请一个 int 类型的空间 int* ptr4 = new int; // 动态申请一个 int 类型的空间并初始化为 10 int* ptr5 = new int(10); // 动态申请 3 个 int 类型的空间 int* ptr6 = new int[3]; // 使用分配的内存 *ptr4 = 5; cout ptr6[i] = i; cout // 捕获内存分配失败的异常 cerr Test(); return 0; } int i = 1; while (1) { int* p1 = new int[1024 * 1024]; cout try { Func(); } catch (const std::exception& e) { cout public: Person(const char* _name,int _age) { name = _name; age = _age; cout cout // 使用 new 创建 Person 对象 Person* person = new Person("Alice", 25); // 使用 delete 释放对象内存 delete person; return 0; } void *p; while ((p = malloc(size)) == 0) { if (用户设置的应对措施函数(size) == 0) { // 申请内存失败,抛出异常 static const std::bad_alloc nomem; throw nomem; } } return p; } if (pUserData == NULL) return; free(pUserData); } // 分配一块原始内存 char* rawMemory = new char[sizeof(int)]; // 使用定位new在原始内存上构造一个int对象 int* intPtr = new (rawMemory) int(42); // 输出构造的int对象的值 std::cout public: MyClass(int value) : data(value) { std::cout std::cout // 分配一块原始内存 char* rawMemory = new char[sizeof(MyClass)]; // 使用定位new在原始内存上构造一个MyClass对象 MyClass* myObjPtr = new (rawMemory) MyClass(10); // 显式调用析构函数 myObjPtr-~MyClass(); // 释放原始内存 delete[] rawMemory; return 0; } // 必须判空! // 处理内存不足的情况 } int* p = new int; // 失败会抛异常,不会返回 NULL } catch (std::bad_alloc& e) { // 处理异常 }
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。