在C语言中,如果我=我们需要动态开辟一块空间,会用到下面这几个函数:
malloc:
void* malloc(size_t size);
malloc函数是在内存中开辟一段连续的空间,开辟的大小为size个字节。开辟成功之后会返回这块空间的首地址
calloc:
void* calloc(size_t num, size_t size);
calloc和malloc相似也是开辟一块连续的空间。num为元素的个数,size为单个元素的字节数
空间的大小为:元素的个数 * 单个元素的字节数
注意:函数calloc会将所分配的空间全部初始化为0。
realloc:
void* realloc(void* ptr, size_t size);
realloc函数是给一个已经分配地址的指针重新分配空间,参数ptr为原有的空间指针,size为重新申请的地址长度。它和malloc的区别就是如果你给的指针是NULL,那么你使用的就是malloc,如果你给出的指针是一个已经分配了地址的指针,那么你使用的就是realloc
realloc可以对给定的指针所指向的空间进行扩大或缩小,如果扩大,原空间数据不变(可能会因为后序空间不足重现开辟空间,所以地址可能会变),扩大的部分会被初始化为0。缩小的话被缩小的的部分就会丢失
free:
void free(void* ptr);
free()函数主要是对ptr指向的空间进行释放
malloc和free是一 一对应的,用malloc开辟出来的空间必须要用free释放
上面所谈的都是C语言管理内存的方法,接下来说说在C++中是如何动态开辟内存的。
在C++中是用new和delete来管理内存的
先来看看new/delete和malloc/free的区别:
- malloc/free是C标准库的函数,而new/delete是C++中的操作符
- malloc/free只是动态分配/释放内存空间,而new/delete除了分配空间还会调用构造函数和析构函数给对象进行初始化和清理
- malloc/free需要手动计算类型大小并且会返回void*,new/delete可以自己计算类型的大小,返回对应类型的指针
new/delete的底层实现:new的底层调用的是operator new,delete的底层调用的是operator delete,它们只负责分配空间和释放空间。实际上operator new和operator delete底层也是封装malloc和free
new实际上做了两件事:
- 调用operator new分配空间
- 调用构造函数初始化空间
delete也是做了两件事
- 调用析构函数清理对象
- 调用operator delete释放空间
new[N]做的事:
- 调用operator new分配空间
- 调用N次构造函数分别初始化每个对象
delete[N]做的事
- 调用N次析构函数清理对象
- 调用operator delete释放空间
那么delete[N]怎么会知道自己需要调用多少次析构函数呢?
这是因为调用new[N]的时候会多开辟四个字节,放在对象的最开始,里面存放的就是N