一、内存四区
内存四区分为:
- 栈区:存储一些临时变量的区域,临时变量包括了局部变量、返回值、参数、返回地址等,当这些变量超出了当前作用域时将会自动弹出。该栈的最大存储是有大小的,该值固定,超过该大小将会造成栈溢出。栈的顶部为地址的最小索引,栈中变量是先进后出。
- 堆区:是一个比较大的内存空间,主要用于对动态内存的分配;在程序开发中一般都是开发人员进行分配与释放,若在程序结束时都未释放,系统将自动进行回收。
- 数据区:主要存放全局变量、常量和静态变量的区域,数据区又可以进行划分,分为全局区与静态区。全局变量与静态变量将会存放至该区域。
- 代码区:主要存储可执行代码,该区域的属性是只读。
二、malloc和free
在C语言中(不是C++),malloc和free是系统提供的函数,成对使用,用于从堆中分配和释放内存。malloc的全称是memory allocation译为“动态内存分配”。
malloc函数的原型如下:
void *malloc(size_t size);
在malloc函数中,size表示需要申请的内存空间大小,申请成功将会返回该内存空间的地址;申请失败则会返回null,并且申请成功也不会自动进行初始化。
所以,当执行语句:
char* mp = (char*)malloc(sizeof(char) * 10);
后,我们可以检查mp的内存,内存中的值都是未初始化的值。如果我们初始化的话:
char* mp = (char*)malloc(sizeof(char) * 10);
memset(mp, 0xFF, sizeof(char) * 10);
检查内存你会发现全是0xFF。当然我们还有另外一个函数:
char* mp = (char*)calloc(10, sizeof(char));
这个函数在分配空间的时候会将值全部设置为0。
在分配内存时需要注意,即使在程序关闭时系统会自动回收该手动申请的内存,但也要进行手动释放,保证内存能够再不需要时返回至堆空间,使内存能够合理的分配使用。
char* mp = (char*)malloc(sizeof(char) * 10);
free(mp);
mp = NULL;
free()释放了由动态分配内存函数返回的指针对应的内存空间,free释放的是内存空间,而不是指针。指针仍然指向分配的内存空间,指针指向的地址没有变化,地址内的内容可能变了。释放指的是指针指向的内存空间可以被其他变量所占用,但被占用前,内存空间中的内容仍然存在,但是无法判断是否被占用。并且在一次free后没有再次被分配空间的情况下,不能再次被free。
使用了free释放了内存,需要将指针赋值Null,不能使指针指向未知的地址,要置于Null;否则在之后的开发者会误以为使个正常的指针。
三、new和delete
C++中使用new和delete从堆中分配和释放内存,new和delete使运算符,不是函数,两者成对使用。new和delete除了分配内存和释放内存,还可以做更多的事情,所以在C++中不再使用malloc和free而使用new和delete。
1、开辟单个元素
type* name=new type(content);
delete name;
可以理解为动态申请一个type类型的空间并将其中内容初始化为content,当然,你也可以选择不初始化。
int* a = new int(100);//动态申请一个int类型的空间并初始化为100;
cout << "a:" << *a << endl;
delete a;
a = NULL;
2、开辟n个type类型的空间
type* name=new type[n];
delete[] name;
int* a = new int[10];//动态申请10个int类型的空间;
delete[] a;
a = NULL;
3、对于内置类型,malloc/free和new/delete确实没有什么区别,二者的作用完全一样。
4、new/delete操作自定义类型
在申请自定义类型空间的时候,new会调用构造函数,delete会调用析构函数,而malloc和free不会。
四、new和delete底层实现原理
在介绍底层实现原理之前我们先介绍一下两个全局函数,分别是operator new和operator delete。new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete全局函数来释放空间。
operator new实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则指向用户提供饿空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete最终是通过free来释放空间。