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对象在使用之前分配,在程序结束时销毁。
- 堆内存:
在程序运行时分配。动态对象的生存周期由程序(用户)来控制。