C++:内存管理

2023-10-28

目录

学习目标

1. C/C++内存分布

2. C/C++动态内存管理

2.1 C动态内存管理

2.2 C++动态内存管理:

3. operator new与operator delete函数

4. new和delete的实现原理

5. 定位new表达式

学习目标

1. C/C++内存分布
2. C/C++动态内存管理(malloc,free 与new ,delete)
3. operator new与operator delete函数
4. new和delete的实现原理
5. 定位new表达式(placement-new)

1. C/C++内存分布

C/C++的内存分布:栈,堆,静态区,代码段

  • 1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  • 2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)
  • 3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
  • 4. 数据段--存储全局数据和静态数据。
  • 5. 代码段--可执行的代码/只读常量。

代码:

int globalVar               = 1;
static int staticGlobalVar  = 1;
void Test()
{
	static int staticVar = 1;
	int localVar         = 1;
	int num1[10]         = { 1, 2, 3, 4 };
	char char2[]         = "abcd";
	const char* pChar3   = "abcd";
	int* ptr1            = (int*)malloc(sizeof(int) * 4);
	int* ptr2            = (int*)calloc(4, sizeof(int));
	int* ptr3            = (int*)realloc(ptr2, sizeof(int) * 4);
	free(ptr1);
	free(ptr3);
}


2. C/C++动态内存管理

2.1 C动态内存管理

C语言中动态内存管理方式:malloc/calloc/realloc/free

代码:

void Test ()
{
    int* p1 = (int*) malloc(sizeof(int));
    free(p1);

    int* p2 = (int*)calloc(4, sizeof (int));
    int* p3 = (int*)realloc(p2, sizeof(int)*10);

    free(p3 );
}

--malloc/calloc/realloc的区别是什么?

1.malloc函数用于分配指定大小的内存块(它只分配内存,不会初始化内存块中的内容)

2.calloc会将内存块的内容初始化为0

3.realloc用于更改先前分配的内存块的大小。(原地修改/重新开一块空间)

2.2 C++动态内存管理:

C++动态内存管理:通过new和delete操作符进行动态内存管理

1.内置类型

代码:

void Test()
{
     // 动态申请一个int类型的空间
     int* ptr4 = new int;
     // 动态申请一个int类型的空间并初始化为10
     int* ptr5 = new int(10);
     // 动态申请10个int类型的空间
     int* ptr6 = new int[3];
     delete ptr4;
     delete ptr5;
     delete[] ptr6;
}

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用
new[]和delete[],注意:匹配起来使用

2.自定义类型

代码:

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
    //还会调用构造函数和析构函数
		A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	free(p1);
	delete p2;
	// 内置类型是几乎是一样的
	int* p3 = (int*)malloc(sizeof(int)); // C
	int* p4 = new int;
	free(p3);
	delete p4;
	A* p5 = (A*)malloc(sizeof(A) * 10);
	A* p6 = new A[10];
	free(p5);
	delete[] p6;
	return 0;
}

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。


3. operator new与operator delete函数

  • 1.new和delete是用户进行动态内存申请和释放的操作符
  • 2.operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

代码:

operator new:

//operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;
//申请空间失败,尝试执行空间不足应对措施,如果该应对措施用户设置了,则继续申请,否则抛异常。
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
	// try to allocate size bytes
	void* p;
	while ((p = malloc(size)) == 0) 
	{
		if (_callnewh(size) == 0)
		{
			// report no memory
			// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
			static const std::bad_alloc nomem;
			_RAISE(nomem);
		}
	}

	return (p);
}

operator delete:

//operator delete: 该函数最终是通过free来释放空间的
void operator delete(void* pUserData)
{
	_CrtMemBlockHeader* pHead;
	RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
	if (pUserData == NULL)
		return;
	_mlock(_HEAP_LOCK);  /* block other threads */
	__TRY
		    /* get a pointer to memory block header */
		pHead = pHdr(pUserData);
	     /* verify block type */
	_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
	_free_dbg(pUserData, pHead->nBlockUse);
	__FINALLY
		_munlock(_HEAP_LOCK);  /* release other threads */
	__END_TRY_FINALLY
		return;
}
//free的实现
#define  free(p)        _free_dbg(p, _NORMAL_BLOCK)

operator new 实际也是通过malloc来申请空间,

如果malloc申请空间成功就直接返回,

否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的


4. new和delete的实现原理

1.内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,

不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL

2.自定义类型

  • new的原理

        1. 调用operator new函数申请空间

        2. 在申请的空间上执行构造函数,完成对象的构造

  • delete的原理

        1. 在空间上执行析构函数,完成对象中资源的清理工作

        2. 调用operator delete函数释放对象的空间

  • new T[N]的原理

        1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请

        2. 在申请的空间上执行N次构造函数

  • delete[]的原理

        1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

        2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间


5. 定位new表达式

作用:定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象

使用:new (place_address) type或者new (place_address) type(initializer-list)
           place_address必须是一个指针,initializer-list是类型的初始化列表

代码:

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
// 定位new/replacement new
int main()
{
	// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
		A* p1 = (A*)malloc(sizeof(A));
	new(p1)A; // 注意:如果A类的构造函数有参数时,此处需要传参
	p1->~A();
	free(p1);
	A* p2 = (A*)operator new(sizeof(A));
	new(p2)A(10);
	p2->~A();
	operator delete(p2);
	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++:内存管理 的相关文章

  • 运行 t4 脚本作为 resx 文件的自定义工具

    我有一个资源文件MyResource resx 我想改变MyResource Designer cs文件生成 我有一个 t4 脚本 它接受 resx 文件作为输入并给出结果转换 但是 我必须手动运行此 t4 才能使其工作 我看到 resx
  • C++ 返回值、引用、const 引用

    你能向我解释一下返回值 值引用和值常量引用之间的区别吗 Value Vector2D operator const Vector2D vector this gt x vector x this gt y vector y return t
  • MySql 最后插入 ID,连接器 .net

    我正在使用 MySql Connector net 我需要获取最后一个查询生成的插入 id 现在 我假设返回值是MySqlHelper ExecuteNonQuery应该是最后一个插入id 但它只返回1 我正在使用的代码是 int inse
  • 每次调用新方法时触发事件

    我正在做一个logger for a c 应用程序需要记录每个方法被调用的时间以及每个方法执行时间 我可以通过调用自己的方法来做到这一点EventLogger LogMethodCall方法在每个方法的开头 但我想知道是否有办法使CLR每次
  • 如何启动异步任务对象

    我想开始收集Task同时处理对象并等待所有对象完成 下面的代码显示了我想要的行为 public class Program class TaskTest private Task createPauseTask int ms works w
  • 在 DataGridView 中隐藏行非常慢

    我在 Winforms 应用程序中有一个 DataGridView 大约有 1000 行 未绑定 和 50 列 隐藏一列需要整整 2 秒 当我想隐藏大约一半的行时 这就成为一个问题 private void ShowRows string
  • 在 C# 中调用事件处理程序

    我一直在尝试学习如何在 C 中使用事件处理程序 但我无法弄清楚 handler this e 在以下代码中的作用 public event EventHandler ThresholdReached protected virtual vo
  • 是否有一种算法可以在线性时间内计算数组反转?

    我知道有多少倒转 en wikipedia org wiki Inversion 28discrete mathematics 29 in an n 元素数组可以在 O n log n 操作使用增强型归并排序 http www geeksf
  • C++:初始化静态字符串成员

    我在 C 中初始化静态字符串成员时遇到一些问题 我有几个类 每个类都包含几个表示 id 的静态字符串成员 当我通过调用静态函数初始化变量时 一切都很好 但是 当我想为一个变量分配另一个变量的值时 它仍然保留空字符串 这段代码有什么问题 st
  • C for 循环索引:新 CPU 中的前向索引更快吗?

    在我订阅的邮件列表上 两位知识渊博的 IMO 程序员正在讨论一些优化的代码 并说了以下内容 在 5 8 年前发布的 CPU 上 向后迭代 for 循环稍微快一些 e g for int i x 1 i gt 0 i 因为比较i归零比将其与其
  • 使用宏计算源文件行数?

    是否可以使用 C C 预处理器将源文件中的行数计算为宏或某种编译时可用值 例如 我可以更换吗MAGIC1 MAGIC2 and MAGIC3在下面 并在使用时以某种方式获取值 4MAGIC3 MAGIC1 can be placed whe
  • SQL参数化查询不显示结果

    我的 DataAcess 类中有以下函数 但它没有显示任何结果 我的代码如下 public List
  • TreeView:仅在子节点中存在复选框

    我需要一个树视图控件 根节点没有复选框 只有图像 所有子节点都有一个复选框 图像 C net 2 0 winforms 不是 wpf WinForms树视图默认不支持混合复选框 非复选框节点 您可以在树视图上全局启用复选框 并使用以下命令在
  • 非静态类中的静态方法和静态类中的静态方法有什么区别?

    我有两个班级A级和B级 static class ClassA static string SomeMethod return I am a Static Method class ClassB static string SomeMeth
  • char* argv[] 在 c/c++ 中如何工作? [复制]

    这个问题在这里已经有答案了 我知道它用于使用命令行中的参数 但我没有得到声明 字符 argv 它是否意味着指向 char 数组的指针 如果是的话为什么没有大小 如果不是动态数组 就不需要有大小吗 我做了一些研究 发现有人说它会衰减为 cha
  • 参数数量在编译时确定的 Lambda 函数

    我想声明一个带有 N 个参数的 lambda 函数 其中 N 是模板参数 就像是 template
  • 为什么我不能对普通变量进行多态?

    我是一名Java程序员 最近开始学习C 我对某事感到困惑 据我了解 在 C 中 要实现多态行为 您必须使用指针或引用 例如 考虑一个类Shape与实施的方法getArea 它有几个子类 每个子类都以不同的方式重写 getArea 然后考虑以
  • 字符串 c 的二叉树

    我正在尝试实现一个能够在 c 中保存字符串的二叉树 在让代码适用于整数之后 我尝试稍微修改它以处理字符数组 现在我似乎完全破解了代码 但不知道如何破解 任何帮助表示赞赏 include
  • 修改代码以从 Windows 中的 PE 可执行文件检索双重签名信息?

    我已经挣扎了一段时间想要修改这段代码示例 https support microsoft com en us help 323809 how to get information from authenticode signed execu
  • 如何在用户空间程序中使用内核 libcrc32c (或相同的函数)?

    我想在我自己的用户空间程序中进行一些 CRC 检查 我发现内核加密库已经在系统中 并且支持 SSE4 2 我尝试直接 include

随机推荐

  • linux 挂载磁盘 普通用户读写 --chatGPT

    问 mount 挂载共享磁盘 指定用户fly可以读写 gpt 要将共享磁盘挂载并授予用户 fly 读写权限 您可以使用 mount 命令结合合适的挂载选项 首先 您需要确保磁盘已经连接到系统上 然后 按照以下步骤进行操作 1 创建一个目标目
  • CPU 与 GPU 之间数据转换 cudaMemcpy

    显存上分配空间 CUDA SAFE CALL cudaMalloc void Dst d sizeof float3 totalPNum 显存上传输数据 CUDA SAFE CALL cudaMemcpy Dst d Srcdata0 h
  • HAProxy--理论--02--配置文件

    HAProxy 理论 02 配置文件 1 配置文件组成 1 global 设置全局配置参数 2 defaults 设置的默认参数 3 frontend 接收请求的前端虚拟节点 Frontend可以直接指定具体使用后端的backend 4 b
  • anaconda 激活环境 并 安装相关包 torch 安装matplotlib

    1 管理员身份 运行 anaconda prompt 2 激活环境 查看python版本 activate 环境名称 3 查看已经安装的包 4 安装所需的包 方法1 pip install matplotlib 如果太慢建议更换国内镜像源
  • vue中给dom元素绑定js原生onclick事件并获取data中定义的数据和调用函数

    onclick 执行的是 window 环境中的方法 所以 将 this 中的方法或data中定义的字段关联到 window 上即可 vue代码 mounted window customMethods this customMethods
  • MariaDB+SpringBoot 报错 Caused by: java.sql.SQLException: GSS-API authentication exception

    最近在搭建springboot mybatis mariadb 项目的时候遇到了如题的问题 搜索了一圈没找到合适的解决方法 因此记录下我的解决方案 希望对后来者有帮助 先说结论 重装MariaDB即可 1 环境和配置信息 开发环境 win1
  • 排序基础算法(一)—— 堆排序

    堆排序 前言 1 完全二叉树 2 大根堆和小根堆 3 堆排序原理 一 调整堆 二 建初堆 三 堆排序算法的实现 Java代码 前言 堆排序是一种树形选择排序 在排序过程中 将待排序的记录r 1 n 看成是一棵完全二叉树的顺序存储结构 利用完
  • ffmpeg基础(五) I帧B帧P帧

    一 I帧 关键帧 属于帧内压缩 你可以理解为这一画面的完整保留 解码的时候只需要本帧的数据就可以完成 因为它包含的是完整信息 特点 1 它是一个全帧压缩编码帧 将全帧图像进行JPEG压缩以及传输 2 解码的时候只需要通过I帧的数据就可以得到
  • C++primer Plus 第三章复习题

    1 为什么C 有多种整型 有多种整型 可以根据输出结果选择最合适的类型 比如年龄可以使用short 存储容量用long 2 声明与下述描述相符的变量 a short整型 值为80 short num 80 b unsigned int 整型
  • python时间相减_python 计算时间差,时间加减运算代码

    1 方便的计算两个时间的差 如两个时间相差几天 几小时 import datetime d1 datetime datetime 2009 3 23 d2 datetime datetime 2009 10 7 dayCount d1 d2
  • MsSQL数据备份与恢复---完全备份与增量备份

    文章目录 1 数据备份 1 1 数据备份的重要性 1 2 数据备份的分类 1 2 1 从物理与逻辑的角度分类 1 2 2 从数据库的备份策略角度分类 1 2 3 备份方式的比较 1 3 常见的备份方法 2 MySQL完全备份与恢复 2 1
  • 扩容 磁盘、pv、lv

    因虚似机上的磁盘空间不够了 试了下偏门的扩展方法 root hdss7 21 df h Filesystem Size Used Avail Use Mounted on devtmpfs 1 9G 0 1 9G 0 dev tmpfs 1
  • Datawhale&Git-Model:假设检验2-多元数值向量的检验

    作业 为研究东 中 西部各省市规模以上的企业发展状况 我们收集了各城市企业的主要经济指标 包括 总资产贡献率 资产负债率 流动资产周转次数 工业成本费用利润率 产品销售率 我们用变量 类别 定义了各类城市 其中1为东部城市 2为中部城市 3
  • openwrt单网口进不了登录界面

    图一 图二 图一是刷完固件后 图二是网线直连电脑的IP配置 进不了登录界面 也ping 不通 请教是什么原因
  • 使用命令恢复postgres数据库报错psql: FATAL: role "root" does not exist 解决方案

    因为是从其他地方备份出来的sql文件 如果直接用pgAdmin4因为格式问题报错input file appears to be a text format dump Please use psql 所以换用命令行执行 但是出现psql F
  • 如何使用vant库的loading组件

    第一步 main js文件引入下载的loading 全局引入ui组件 import Vant from vant import vant lib index css Vue use Vant 第二步 在vuex中定义全局变量loading
  • Java Utils工具类大全

    源码和jar见 https github com evil0ps utils Java Utils 封装了一些常用Java操作方法 便于重复开发利用 另外希望身为Java牛牛的你们一起测试和完善 欢迎入群263641914 一起封装和完成常
  • 鉴权大全(cookie、session、token、jwt、单点登录),深入理解和搞懂鉴权

    先从状态说起吧 众所周知http是无状态的协议 也就是说 HTTP 请求方和响应方间无法维护状态 都是一次性的 它不知道前后的请求都发生了什么 是不是可以单纯的理解为它是一个超级无敌健忘的协议 但有的场景下 我们需要维护状态 最典型的 一个
  • 关于mipi camera 传输速率的计算

    假设图片的分辨率是 1600x1200 帧率按照 30HZ来计算 在理想状态下 未包含 RGB 信号的前后肩宽度 总传输速率为 1600x1200x24x30 1024 1024 1318 4Mbps 如果是单通道传输 则每通道数据传输速率
  • C++:内存管理

    目录 学习目标 1 C C 内存分布 2 C C 动态内存管理 2 1 C动态内存管理 2 2 C 动态内存管理 3 operator new与operator delete函数 4 new和delete的实现原理 5 定位new表达式 学