1.c与c++的内存分布
1.1静态全局变量与普通全局变量的区别
链接属性不一样:普通全局变量在所有文件中都可见,但是静态全局变量仅在当前文件可见。
对于静态的全局变量:在main函数之前就已经初始化,在哪儿都可以使用,作用域是全局的。
对于静态的局部变量:运行到该处再初始化,作用域为该函数中,只能在该函数中使用。
以下为c/c++中程序内存区域的划分图。
2.c语言中的动态内存管理
2.1malloc,calloc,realloc/free
malloc为直接在堆上申请一份内存空间,calloc为malloc的基础上进行初始化,realloc为在原有基础空间上进行扩容。
3.c++中动态内存管理
c语言的内存管理方式在c++中仍可继续使用,但有些地方用起来存在问题,故c++引入了自己的内存管理方式,用new和delete操作符进行动态内存管理。
3.1new和delete的操纵内置类型
void Test()
{
//动态申请一个int类型的空间
int* ptr1=new int;
//动态申请一个int类型的控件并且初始化为3
int* ptr2=new int(3);
//动态申请3个int类型的空间
int* ptr3=new int[3];
delete ptr1;
delete ptr2;
delete[] ptr3;
}
申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意匹配起来使用。
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc和free不会。(对于内置类型,都是一样的)
//内置类型
int* p1=new int;
int* p2=(int*)malloc(sizeof(int));
//自定义类型
A* p3=(A*)malloc(sizeof(A)); //仅申请空间
A* p4=new A; //申请空间同时调用构造函数初始化
free(p3); //仅释放空间
delete p4; //析构函数+释放空间
4.operator new和operator delete函数
4.1operator new和operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过调用operator delete全局函数来释放空间。
1.malloc
2.operator new: malloc+失败抛异常
3.new: operator new+构造函数
4.new相比于malloc不一样的地方: 1.调用构造函数 2.失败抛异常
5.delete比起free不一样的地方: 1.调用析构函数清理
6.operator free和free没区别,因为释放空间失败直接终止进程,引出是因为operator new和new成对出现。
int main()
{
A* p1=new A;
delete p1;
//拆解模拟new和delete一片空间
A* p2=(A*)operator
}
5.new和delete的实现原理
5.1内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申
请空间失败时会抛异常,malloc会返回NULL。
5.2自定义类型
new的原理
- 调用operator new函数申请空间。
- 在申请的空间上执行构造函数,完成对象的构造。
delete的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
new T[N]的原理
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请 - 在申请的空间上执行N次构造函数
delete[N]的原理
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间
6.定位new表达式(placement-new)
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如
果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。