C语言使用malloc/realloc/calloc/free进行内存管理。C++通过操作符new和delete进行内存管理。new/delete动态管理对象,new[]/delete[]动态管理对象数组。
void Test()
{
int* p1 = new int;//动态开辟4个字节空间(一个int)单个数据
int* p2 = new int(3);//动态开辟4个字节空间(一个int)并初始化为3
int* p3 = new int[3];//动态开辟12个字节空间(3个int)的空间
delete p1;
delete p2;
delete[] p3;
}
注意:malloc/free,new/delete,new[]/delete[]一定要匹配使用,不然可能会导致内存泄露。
malloc/free和new/delete的区别和联系
- 它们都是动态管理内存的入口。
- malloc/free是C标准库的函数,new/delete是C++的操作符。
- malloc和free只是动态开辟内存/释放内存的,new/delete不仅开辟空间还调用构造函数和析构函数进行初始化和清理(清理成员)。
- malloc/free需要手动计算类型大小且返回void*,new/delete可自己计算类型的大小,返回对应类型的指针。
malloc失败了返回0,delete失败了抛异常。
C++的其他内存管理接口:
void* operator new(size_t size);
void operator delete(size_t size);
void* operator new[](size_t size);
void operator delete[](size_t size);
new表达式与operator new函数
标准库函数operator new和operator delete的命名容易让人误解,与其他operator函数不同,这些函数没有重载new和operator表达式,实际上,我们不能重定义new和delete表达式的行为。
总结:
1.operator new/operator delete/operator new[]/operator delete[]和malloc/free用法一样。
2. 他们只负责开辟空间/释放空间,不调构造函数/析构函数来初始化/清理对象。
3. 实际operator new/operator delete是malloc/free的一层封装。
new做了两件事:
- 调用operator new开辟空间
调用构造函数初始化对象。
delete也做了两件事:
- 调用析构函数清理对象。
调用operator delete释放空间
new[N]
调用operator new分配空间。
调用N次构造函数分别初始化对象。
delete[N]
- 调用N次析构函数分别清理对象。
调用operator delete释放空间。
new/delete,new[]/delete[]系统到底做了什么?
delete[]的对象是自定义类型时,是怎么知道要调用N次析构函数的?
这个问题导致我们需要在new[]一个对象数组时,需要保存数组的维度,C++的做法是在分配数组空间时多分配4个字节的大小,专门保存数组的大小,在delete[]时就可以取出这个保存的数,就知道需要调用析构函数多少次了。
注意:调用析构函数的次数是从数组对象指针前面的4个字节中取出;
- 传入operator delete[]函数的参数不是数组对象的指针p,而是p的值减4。