1、C/C++内存分布
程序中需要存储一些数据,这些数据包括局部数据、静态数据和全局数据、常量数据、动态申请数据,程序会将内存区域划分多个部分,将不同的数据存放在相应的区域。如下图所示,其中栈是向下增长的,用于存储一些局部数据。堆是向上增长的,用于实现动态分配内存,也就是函数中的动态申请数据的部分。静态区也叫做数据段,函数中的静态数据和全局数据都是存储在这里。常量区也叫做代码段,用于存储程序中的常量数据和可执行的代码。
2、C语言中动态内存管理方式:malloc/calloc/realloc/free
那么他们之间的区别是什么呢?
1、malloc:
用于分配一块指定大小的内存,malloc分配的内存块的内容是未初始化的,即里面的值是随机的,如果分配成功则返回一个指向分配内存的指针,如果分配失败,则返回NULL
2、calloc
用于分配一块内存,并初始化为零,如果成功则返回一个指向分配内存的指针,如果失败则返回NULL
3、realloc
用于重新调整已经分配的内存块的大小,可能会在原位置扩展内存(如果原位置依然有空间可供使用),也可能会将其移动到新的位置并将原来的内容复制到新的内存位置上。如果成功,返回指向新的内存区域的指针,如果失败,返回NULL且不释放原内存块
3、C++内存管理方式
C++中使用new和delete操作符进行动态内存管理
1)对于内置类型
new/delete和malloc/free几乎是一样的
cpp
void Test()
{
//动态申请一个int类型的空间
int* ptr4=new int;
//动态申请一个int类型的空间并初始化为10
int* ptr5=new int(10);
//动态申请10个int类型的空间
int* ptr6=new int[3];
delete ptr4;
delete ptr5;
delete[] ptr6;
}
申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意要匹配起来进行使用
2)对于自定义类型
对于自定义类型new/delete除了开空间还会调用构造函数和析构函数,但是malloc/free不会
cpp
class A
{
public:
A(int a=0)
:_a(a)
{
cout<<"A():"<<endl;
}
~A()
{
cout<<"~A():"<<endl;
}
private:
int _a;
}
int main()
{
A* p1=(A*)malloc(sizeof(A));
A* p2=new A(1);
free(p1);
delete p2;
A* p5=(A*)malloc(sizeof(A)*10);
A* p6=new A[10];
free(p5);
delete[] p6;
}
4、operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new和operatordelete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
而operator new实际通过malloc来申请空间,当malloc申请空间成功时会直接返回,若申请失败则抛异常,operator delete是通过free来释放空间的
总结:
new/delete和malloc/free在使用时,对于申请内置类型的空间,二者区别并不大,只不过new/delete可以申请和释放单个元素的空间,也可以使用new[]/delete[]来申请连续的空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
new/delete和malloc/free在使用时,对于申请自定义类型的空间区别较大,new会调用operator new函数来申请空间,再在申请的空间上执行构造函数来完成对象的构造。delete会在空间上执行析构函数完成对象中资源的清理工作,再调用operator delete函数释放对象的空间。new T[]和delete[]也是类似的,new T[]会先调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请,再在申请的空间上执行N次构造函数。delete[]是在释放的对象空间上执行N次析构函数,完成N个对象中的资源清理,再调用operator delete[]释放空间,实际也是调用operator delete来释放空间