C/C++:动态内存管理方式的区别
C语言中动态内存管理方式
malloc/calloc/realloc和free
代码示例
void Test () { int* p1 = (int*)malloc(sizeof(int)); free(p1); // 1.malloc/calloc/realloc的区别是什么? int* p2 = (int*)calloc(4, sizeof (int)); int* p3 = (int*)realloc(p2, sizeof(int)*10); // 2.这里需要free(p2)吗? free(p3); }
1. malloc/calloc/realloc的区别是什么?
解答:
void * malloc(size_t); // 要申请空间的字节数 void * calloc(size_t, size_t); // 第一个参数申请的元素个数;第二个参数是单个元素类型的大小 void * realloc(void *, size_t); void * free(void *);
- malloc 开辟空间不会进行初始化
- calloc 会初始化空间为0
- realloc 是将 p 指向的空间调整到 size 的字节(当第一个参数传入NULL的时候和malloc一样)
假设:p 指向的空间原来的大小为 oldsize 字节
-
size <= oldsize:需要将 p 指向的空间缩小到 size 字节(返回的还是原来空间的地址) size > oldsize:需要将 p 指向的空间扩增到 size 个字节。 p 之后没有被使用的空间足以支持本次扩增,返回 p 原来空间的手地址 p 之后没有被使用的空间不足以支持本次扩增 开辟新空间 拷贝元素 释放旧空间 返回新空间
2.这里需要free(p2)吗?
解答:
这里不需要free(p2);
realloc的操作步骤如下:
- 申请size个字节的空间
- 将 p 中的值拷贝到刚申请的空间中
- 释放 p,返回刚申请的空间
C++动态内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
new/delete操作内置类型
void Test() { // 动态申请一个int类型的空间 int* ptr4 = new int; // 动态申请一个int类型的空间并初始化为10 int* ptr5 = new int(10); // 动态申请3个int类型的空间 int* ptr6 = new int[3]; delete ptr4; delete ptr5; delete[] ptr6; }
注意:
-
申请和释放单个元素的空间,使用new和delete操作符 申请和释放连续的空间,使用new[]和 delete[]
new和delete操作自定义类型
class Test { public: Test() : _data(0) { cout<<"Test():"<<this<<endl; } ~Test() { cout<<"~Test():"<<this<<endl; } private: int _data; }; void Test2() { // 申请单个Test类型的空间 Test* p1 = (Test*)malloc(sizeof(Test)); free(p1); // 申请10个Test类型的空间 Test* p2 = (Test*)malloc(sizoef(Test) * 10); free(p2); } void Test2() { // 申请单个Test类型的对象 Test* p1 = new Test; delete p1; // 申请10个Test类型的对象 Test* p2 = new Test[10]; delete[] p2; }
注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。 所以在给类分配空间时,最好使用new/delete
知识点习题
- malloc函数进行内存分配是在什么阶段?
A. 编译阶段 B. 链接阶段 C. 装载阶段 D. 执行阶段
正确答案
D
答案解析
程序占用三种类型的内存:静态内存、栈内存、堆内存;
-
静态内存:
用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量
-
栈内存:
用来保存定义在函数内的非static对象。 分配在静态内存或栈内存中的对象由编译器自动创建和销毁。对于栈对象,仅在其定义的程序块运行时才存在;static对象在使用之前分配,在程序结束时销毁。
-
堆内存:
在程序运行时分配。动态对象的生存周期由程序(用户)来控制。