C++ 的内存管理与 C 的内存管理
目录
- 1 内存的划分
- 2 C 语言的动态内存管理方式
- 3 C++的内存管理方式
- 3.1 new 和 delete 的使用方式
- 3.2 new 和 delete 对于自定义类型
- 4 C 与 C++ 内存管理的对比
1 内存的划分
在进行对比之前,我们首先需要知道内存的划分形式以及内存的每块区域是用来存储什么样的数据的
内存主要被划分为栈,堆,数据段(静态区),代码段,内存映射段,内核空间
我们需要关注的部分为:栈,堆,数据段(静态区),代码段
栈: 栈顶位于高地址,栈底位于低地址,向下进行增长,主要用于存储形式参数,局部变量等
堆: 堆顶位于低地址,堆底位于高地址,向上进行增长,主要用来存储动态开辟出来的空间(malloc/calloc/realloc/free)
数据段(静态区): 主要用来存放静态变量和全局变量
代码段: 主要用来存储代码和常量
2 C 语言的动态内存管理方式
C 语言要进行动态内存管理,就离不开 malloc/calloc/realloc/free 这四个函数,接下来进行简要介绍
- malloc: 作用是在堆上进行空间的分配,大小由用户自己指定,分配完成后,会返回指向那块空间的指针,类型为 void*,用户可根据需要来进行类型转换
- calloc: 作用是在堆上进行空间分配并将该空间进行初始化,分配完成后,会返回指向那块空间的指针,类型为 void*,用户可根据需要来进行类型转换
- realloc: 作用是对已经分配好的空间进行扩充,空间在进行扩充时,有两种方式,一种是在原空间后方进行扩充,另一种是分配新空间,拷贝旧数据并释放原空间,分配完成后,会返回指向那块空间的指针,类型为 void*,用户可根据需要来进行类型转换
- free: 作用是对已经分配好的空间进行释放
int main()
{int* p1 = (int*)malloc(sizeof(int) * 10); //开辟40B的空间int* p2 = (int*)calloc(10, sizeof(int)); //开辟40B的空间并初始化为0int* p3 = (int*)realloc(p1, sizeof(int) * 20); //将p1指向的空间扩充到80Bfree(p2);p2 = NULL;free(p3);p3 = NULL;return 0;
}
在使用 malloc/calloc/realloc 分配自定义类型对象的空间时,只会分配对象的空间,但是不会调用构造函数进行初始化,在使用 free 时,也只会释放给对象分配的空间,但是不会将对象的资源进行释放,因此还需要用户自己调用构造与析构
3 C++的内存管理方式
由于在 C++ 中引入了类和对象,再使用 C语言的动态内存管理方式会十分不方便,所以 C++ 制成了新的动态内存管理方式,也就是 new 和 delete 操作符
3.1 new 和 delete 的使用方式
new 是用来在堆上分配空间的操作符,要使用它,需要指定分配的空间的大小,在成功分配好空间后,它会返回一个指向该空间的指针,如果要对这个空间初始化,需要在类型名后加上 (),() 内是初始化的值,若没有手动初始化,那么它是随机值
示例:使用 new 开辟可存储 1 个 int 类型对象的空间并初始化为 1
int main()
{int* p1 = new int(1); //分配4B的空间并初始化为 1int* p2 = new int; //随机值delete p1;delete p2;return 0;
}
若想用 new 开辟一组连续的空间(类似数组),那么只需要在类型后面加上 [] 与 对象的个数 即可,如果还想对内容进行初始化,就需要在后面写上 {} ,{} 内是要初始化的值,这与数组类似,若没有手动初始化,那么它也会自动初始化为 0
示例:使用 new 开辟可存储 10 个 int 类型对象的空间并初始化为 0
int main()
{int* p1 = new int[10]{0,0,0,0,0,0,0,0,0,0}; //分配4B的空间并初始化为 0int* p2 = new int[10]{0}; //第一个初始化为0,后面自动补0delete[] p1;delete[] p2;return 0;
}
delete 操作符是用来释放已分配的空间的,如果只分配了一个空间,则只需要写成 delete 空间首地址,如果分配了一组空间,则需要写成 delete[] 空间首地址
3.2 new 和 delete 对于自定义类型
在分配自定义类型对象的空间时:
使用 new 会先分配空间,再调用该对象的构造函数
在使用 delete 回收空间时,先调用析构函数将对象的资源释放,再释放给对象分配的空间
class Stack
{typedef int STDataType;
public:Stack(int n = 4):_a(new int[n]), _top(0), _capacity(n){}~Stack(){delete[] _a;_a = nullptr;_top = 0;_capacity = 0;}
private:STDataType* _a;size_t _top;size_t _capacity;
};int main()
{Stack* ps = new Stack; //调用默认构造//Stack* ps = new Stack(5); //传参调用构造delete ps;Stack* ps2 = new Stack[3]{5, 1, 4}; //产生一组对象, {}内是在传参调用构造delete[] ps2;return 0;
}