一、C/C++内存分布
说明:
1.栈(堆栈):非静态局部变量/函数参数/返回值,栈是向下增长的。
2.内存映射段:高效的I/O映射方式,用于装载一个共享的动态内存库,用户可以使用系统创建共享内存,做进程间通信。
3.堆:用于程序运行时动态内存分配,堆是向上增长的。
4.数据段:存储全局数据和静态数据。
5.代码段:可执行的代码/只读常量。
二、C语言动态内存管理方式
(一)malloc/calloc/realloc和free
1.相同点:
(1)从堆上申请空间,必须手动释放。
(2)函数返回类型为void*,申请成功返回首地址,失败返回NULL。
(3)对于三个函数申请的空间,使用之前需要判空。
2.不同点:
(1)malloc:
函数原型:void* malloc(size_t size);
说明:malloc函数有一个参数,即要分配的内存空间的大小。malloc不能初始化所分配的内存空间,但是calloc可以。由于malloc分配的内存空间原来没有被使用过,则其中每一位可能都是0,但是如果这部分内存曾经被使用过,在其中可能有各种各样的数据。
(2)calloc:
函数原型:void* calloc(size_t num,size_t size);
说明:calloc函数将分配的内存空间的每一位初始化为0,也就是说如果为字符型或者数据类型的元素分配内存空间,那么这些元素将被初始化为0,如果是为指针类型的元素分配内存空间,那么这些元素会被初始化为空指针。
(3)realloc:
函数原型:void* realloc(void* memblock,size_t size)
说明:realloc函数是给一个已经分配了内存的地址指针重新分配空间,参数包括原有的空间地址和重新申请的地址长度。
三、C++内存管理方式
class A
{
public:
A(int v)
:_var(v)
{
fopen_s((&file), "test", "r");
}
~A()
{
fclose(file);
}
private:
int _var;
FILE *file;//4个字节
};
int main()
{
class A *pA = new A(10);
return 0;
}
执行以上代码会发生什么?先跳到反汇编看看
在这里插入图片描述
我们看到了operator new
,其实与之相对应的还有operator delete
,他们的原型分别为:
void* operator new(size_t);
void* operator delete(void*);
其实它们的作用和C中的malloc和free有点像,就是用来申请和释放内存的,并且operator new申请内存之后不会对内存进行初始化,而是返回申请内存的指针。
(一)new/delete:
1.new背后实现机制(大致分为以下三步):
(1)首先调用上面的operator new标准库函数,传入的参数为class A的大小,这里为8个字节,这样函数的返回的是分配内存的起始地址。
(2)上面分配的内存是未初始化的,也是未类型化的,第二步就是在这一块原始的内存上对类对象进行初始化,调用的是相应的构造函数,这里调用的是A(10);这个函数,从图中可以看到这块申请的内存进行了初始化,var = 10,file指向打开的文件。
(3)最后一步就是返回新分配并构造好的对象的指针,这里pA指向这块内存,pA的类型为类A对象的指针。
2.delete背后实现机制(大致分为两步):
(1)调用pA指向对象的析构函数,对打开的文件进行关闭。
(2)通过上面提到的标准库函数operator delete来释放该对象的内存,传入函数的参数为pA的值。即之前返回的地址。
总结: new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete全局函数来释放空间。
operator new:该函数是通过malloc来申请空间,当malloc申请空间成功是直接返回;申请空间失败,尝试执行空间不足应对措施,如果该应对措施用户设置了,则继续申请,否则抛异常。
operator delete:该函数最终是通过free来释放空间的。
四、malloc/free和new/delete的区别
(一)相同点:
1.malloc/free和new/delete都是从堆上申请空间,并且需要用户手动释放。
(二)不同点:
1.malloc和free是函数,new和delete是操作符。
2.malloc申请的空间不能初始化,new申请的空间可以初始化。
3.malloc申请空间的时候需要传递空间大小参数,new只需要加上空间的类型。
4.malloc申请空间需要强转,new不需要。
5.malloc申请空间失败返回NULL,所以使用时需要判空,而new不需要,但是需要捕获异常。
6.malloc/free只能申请内置类型的空间,不能申请自定义类型的空间,因为其不会调用构造函数与析构函数,而new可以,new在申请空间后会调用构造函数完成对对象的构造,delete在释放空间时会调用析构函数,完成空间中资源的清理。
7.malloc申请的空间一定在堆上,而new不一定,因为operator new函数可以重新实现。
8.new/delete比malloc/free的效率低一些,因为new/delete底层封装了malloc/free。