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

C++ 分配内存释放内存

C++ 分配内存释放内存

  • 一、new、delete、malloc和free
    • 最简单的分配内存
    • 自定义对象分配和释放内存
  • 二、new、delete与虚析构的问题
  • 三、一维、二维、多维数值创建和释放
    • 一维
    • 二维
    • 多维
  • 四、new的缺点以及连续内存的优点


一、new、delete、malloc和free

最简单的分配内存

	int* p_m = (int*)malloc(sizeof(int));int* p_n = new int;

自定义对象分配和释放内存

让我们定义如下的对象

class TestClass
{
public:TestClass(){cout << "构造函数调用" << endl;}~TestClass(){cout << "析构函数调用" << endl;}int a = 0;int b = 0;
};

然后使用new和malloc分配内存,使用delete和free分别释放

	TestClass* p_m1 = (TestClass*)malloc(sizeof(TestClass));TestClass* p_n1 = new TestClass();delete p_n1;free(p_m1);

我们会发现最终只有new 和 delete 配对的方式走了生命周期
在这里插入图片描述
那我们把他们换过来配对会怎么样呢

	TestClass* p_n1 = new TestClass();free(p_n1);

在这里插入图片描述

	TestClass* p_m1 = (TestClass*)malloc(sizeof(TestClass));delete p_m1;

在这里插入图片描述
可以看到:
delete 释放都会调用析构函数,而free都不会调用。
new 可以调用构造函数,而malloc不会调用构造
如果要使用生命周期的话使用new是较好的选择

二、new、delete与虚析构的问题

我们定义一个有着继承关系的结构

class BaseClass
{
public:BaseClass(){cout << "Base构造函数调用" << endl;}~BaseClass(){cout << "Base~析构函数调用" << endl;}int a = 0;int b = 0;
};class ChildClass : public BaseClass
{
public:ChildClass(){cout << "Child构造函数调用" << endl;}~ChildClass(){cout << "Child~析构函数调用" << endl;}
};

然后我们分配内存和释放内存,看看构造与析构是怎么样的

	ChildClass* Child = new ChildClass();delete Child;

在这里插入图片描述
现在我们使用多态去定义

	BaseClass* Child1 = new ChildClass();delete Child1;

在这里插入图片描述
我们发现这时候并没有调用子类的析构了,我们需要给父类析构变成虚析构
最终代码

class BaseClass
{
public:BaseClass(){cout << "Base构造函数调用" << endl;}virtual ~BaseClass(){cout << "Base~析构函数调用" << endl;}int a = 0;int b = 0;
};class ChildClass : public BaseClass
{
public:ChildClass(){cout << "Child构造函数调用" << endl;}~ChildClass(){cout << "Child~析构函数调用" << endl;}
};int main()
{ChildClass* Child = new ChildClass();delete Child;cout << "=========================" << endl;BaseClass* Child1 = new ChildClass();delete Child1;system("pause");return 0;
}

在这里插入图片描述

三、一维、二维、多维数值创建和释放

一维

	TestClass* Arr = new TestClass[10];delete[] Arr;

二维

	// 创建TestClass** Arr = new TestClass*[3];for (size_t i = 0; i < 3; i++){Arr[i] = new TestClass[3];}// 释放for (size_t i = 0; i < 3; i++){delete[] Arr[i];}delete[] Arr;

多维

	// 创建TestClass*** Arr = new TestClass**[2];for (size_t i = 0; i < 2; i++){Arr[i] = new TestClass*[2];for (size_t j = 0; j < 2; j++){Arr[i][j] = new TestClass[2];}}// 释放for (size_t i = 0; i < 2; i++){for (size_t j = 0; j < 2; j++){delete[] Arr[i][j];}delete[] Arr[i];}delete[] Arr;

四、new的缺点以及连续内存的优点

内存碎片产生原因:

1、小块内存分配​​:
频繁分配不同大小的对象
内存分配器需要不断寻找合适大小的内存块

for (int i = 0; i < 10000; i++) {// 频繁分配不同大小的对象auto* obj1 = new SmallObject();   // 例如 16 字节auto* obj2 = new MediumObject();  // 例如 64 字节auto* obj3 = new LargeObject();   // 例如 256 字节// 释放部分对象delete obj2; // 在内存中留下中等大小的空隙
}

2、非连续释放​​:
对象以随机顺序创建和销毁
在已分配内存中留下大小不一的"空洞"

3、内存分配器限制​​:
无法合并相邻的小空闲块
新分配的对象无法放入这些"空洞"

频繁的new对象会有大量的内存碎片产生,可以预先分配一块内存进行取用

template<typename T>
class FPreCacheData
{
public:FPreCacheData(int size){Size = size;DataPtr = new T[size];}inline int GetSize() { return size; }T& operator[](int index) {return DataPtr[index];}private:int Size;T* DataPtr;
};
	FPreCacheData<TestClass> PreCacheData = FPreCacheData<TestClass>(100);TestClass& a = PreCacheData[20];
http://www.lryc.cn/news/595571.html

相关文章:

  • Anaconda 路径精简后暴露 python 及工具到环境变量的配置记录 [二]
  • 【C#】C# 事件 两次 -= 会怎么样?
  • C# 结构体
  • C# 转换(is和as运算符)
  • XSS学习总结
  • Unreal ARPG笔记
  • 《画布角色的双重灵魂:解析Canvas小游戏中动画与碰撞的共生逻辑》
  • Spring Boot注解详解
  • 影刀 RPA:批量修改 Word 文档格式,高效便捷省时省力
  • 通俗易懂卷积神经网络(CNN)指南
  • 海康威视视觉算法岗位30问及详解
  • 多片RFSoC同步,64T 64R
  • STM32小实验四--按键控制LED灯
  • Neo4j 5.x版本的导出与导入数据库
  • 车载软件架构 --- 软件开发面临的问题
  • DAY17 常见聚类算法
  • Spring AI 集成阿里云百炼与 RAG 知识库,实现专属智能助手(框架思路)
  • SpringSecurity 详细介绍(认证和授权)
  • 广东省省考备考(第五十二天7.21)——数量、判断推理(听课后强化训练)
  • 【qml-3】qml与c++交互第二次尝试(类型方式)
  • Android MTK平台预置多张静态壁纸
  • LinkedList与链表(单向)(Java实现)
  • 跨端分栏布局:从手机到Pad的优雅切换
  • 遗像照片尺寸要求及手机制作打印方法
  • DIDCTF-2021第三届长安杯(检材一)
  • LeetCode 每日一题 2025/7/14-2025/7/20
  • Android Studio 的 Gradle 究竟是什么?
  • 力扣刷题 -- 100.相同的树
  • 4.Java创建对象有几种方式?
  • repmgr+pgbouncer实现对业务透明的高可用切换