从零开始学C++ (内存管理)

1.C/C++内存分布

C/C++中内存主要分为:栈、堆、数据段、代码段、内存映射段。

  1. 栈:又叫堆栈,存放非静态局部变量,函数的参数,返回值、栈是向下增长的。

  2. 堆:用于程序运行时动态分配。

  3. 数据段:存放全局变量,静态变量。

  4. 代码段:存放可执行的代码和常量。

  5. **内存映射段:**是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口

    创建共享共享内存,做进程间通信。

2.C语言中动态内存管理方式

C语言中主要使用malloc,calloc,realloc和free来进行动态内存管理,那么malloc,calloc,realloc有什么区别呢?

1.函数原型与参数不同

  • mallocvoid* malloc(size_t size);

    • 只接收1个 参数:要分配的总字节数
  • callocvoid* calloc(size_t nmemb, size_t size);

    • 接收2个 参数:元素个数单个元素大小 。实际分配的总字节数为 nmemb * size
  • reallocvoid* realloc(void *ptr, size_t new_size);

    • 接收2个 参数:原先的内存指针新的总字节数。它用于调整已存在内存块的大小。

2.初始化行为不同

  • malloc不会初始化 内存。分配的内存中存储的是残留的"脏数据"(随机值)。如果你需要清零,必须手动调用 memset

  • calloc会初始化为 0 。分配完成后,它会将内存块中的所有字节全部置为 0(保证数据安全)。

  • realloc不会初始化新增的部分 。它只负责调整大小,原有的数据内容会被保留 (如果缩小,缩掉的部分丢失;如果扩大,新增加的空间不会清零,同样是脏数据)。

3.C++内存管理

C++使用new和delete来进行动态内存管理

1.new和delete用于内置类型

cpp 复制代码
	//动态申请一个int 类型的空间
	int* p1 = new int;
	//动态申请一个int 类型的空间并初始化为10
	int* p2 = new int(10);
	//动态申请是个int 类型的空间
	int* p3 = new int[10];

	delete p1;
	delete p2;
	delete[] p3;

注意,申请单个空间用new和delete,申请连续空间用new\[\]和delete\[\],要搭配使用。

2.new和delete用于自定义类型

cpp 复制代码
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会调用构造函数和析构函数,malloc和free不调用
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(10);

	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;
}

4.operator newoperator delete****函数

new和delete操作符在底层实际上是调用operator new与operator delete两个全局函数,operator new也是通过malloc来申请空间,申请成功就直接返回,否则就执行用户提供的空间不足应对措施,如果用户提供就继续申请,否则就抛异常,operator delete通过free来释放空间。

5.new和delete的实现原理

1.内置类型

对于内置类型,new和delete与malloc和free基本类似,不同在于new和delete申请和释放的是单个空间,new\[\]和delete\[\]申请和释放的是连续空间,new申请失败会抛异常,malloc申请失败会返回NULL。

2.自定义类型

new和delete

new:

  1. 调用operator new完成空间的申请
  2. 调用构造函数,完成对对象的初始化构造

delete:

  1. 调用析构函数,完成对对象资源空间的清理
  2. 调用operator delete完成空间的释放

new\[\]和delete\[\]

new\[\]:

  1. 调用operator new\[\],实际上operator new\[\]调用operator new完成N次空间的申请
  2. 调用N次构造函数,完成对对象的初始化构造

delete\[\]:

  1. 调用N次析构函数,完成对对象资源空间的清理
  2. 调用operator delete\[\],operator delete\[\]调用operator delete完成N次空间的释放
相关推荐
许彰午2 小时前
100_Python面试常见问题汇总
java·python·面试
weixin_727535623 小时前
Spring @Transactional 事务失效:原理层面深度解析
java·spring
cpp_25014 小时前
P6625 [省选联考 2020 B 卷] 卡牌游戏
数据结构·c++·算法·前缀和·贪心·洛谷题解·省选
没钥匙的锁14 小时前
16-Java反射机制:Spring IOC背后的核心技术
java·开发语言·spring
geinvse_seg4 小时前
飞算JavaAI:把企业采购协同需求拆成一套可运行的慧采平台
java·ai·飞算
烛影摇红透纱窗5 小时前
ForkJoinPool 与工作窃取
java
浩瀚地学5 小时前
【面试算法笔记】0302-哈希表-哈希表实现
java·经验分享·笔记·算法·面试
AC赳赳老秦6 小时前
时间开销自动统计:OpenClaw 记录工作任务时长、分析时间分配、给出优化建议
java·大数据·开发语言·python·自动化·deepseek·openclaw
名侦探7226 小时前
构建 Agent 的五大难点与解决方案
java·大数据·人工智能