1.C的动态内存管理细节
C语言使用malloc/calloc/realloc/free进行动态内存管理。
且需要成对使用,开辟空间使用完之后一定要free掉。
其中,malloc和realloc都是开辟一块空间,返回这块空间的起始地址。但二者有区别,malloc开辟空间返回首地址,realloc开辟空间,并且初始化这块儿空间,然后返回这块空间的首地址。
2.C动态管理在C++中的缺陷引入C++动态内存管理
在C语言中动态内存管理时存在一些缺陷。C语言中开辟空间使用完后只是简单的free掉,而C++中,使用new开辟空间,若为简单内置类型时,和C语言中几乎相同,而若为自定义类型时,开辟空间的同时并且要调用构造函数进行初始化,在delete时调用析构函数进行清理成员。
【malloc/free和new/delete的区别和联系?】
1. 它们都是动态管理内存的⼊⼜。
2. malloc/free是C/C++标准库的函数,new/delete是C++操作符。
3. malloc/free只是动态分配内存空间/释放空间。⽽new/delete除了分配空间还会
调⽤构造函数和析构函数进⾏初始化与清理(清理成员)。
4. malloc/free需要⼿动计算类型⼤⼩且返回值会void*,new/delete可⾃⼰计算类
型的⼤⼩,返回对应类型的指针。
3.C++动态内存管理基本语法和使用
new/delete动态管理对象。
new[]/delete[]动态管理对象数组。
new和delete需成对使用,例如:
4.C++提供的动态内存管理的底层实现及其接口operator new/delete/new[]/delete[]
C++的其他内存管理接⼜(placement版本)
void * operator new (size_t size);
void operator delete (void* p);
void * operator new [](size_t size);
void operator delete[] (void* p);
总结:
1. operator new/operator delete operator new[]/operator delete[] 和 malloc/free⽤法⼀样。
2. 他们只负责分配空间/释放空间,不会调⽤对象构造函数/析构函数来初始化/清理对
象。
3. 实际operator new和operator delete只是malloc和free的⼀层封装。
new做了两件事
1. 调⽤operator new分配空间。
2. 调⽤构造函数初始化对象。
delete也做了两件事
1. 调⽤析构函数清理对象
2. 调⽤operator delete释放空间
new[N]
1. 调⽤operator new分配空间。
2. 调⽤N次构造函数分别初始化每个对象。
delete[]
1. 调⽤N次析构函数清理对象。
2. 调⽤operator delete释放空间。
5.定位new表达式
定位new表达式是在已分配的原始内存空间中调⽤构造函数初始化⼀个对象。
new (place_address) type
new (place_address) type(initializer-list)
place_address必须是⼀个指针,initializer-list是类型的初始化列表。
#include <iostream>
using namespace std;
class Array
{
public:
Array(size_t size = 10)
: _size(size)
, _a(0)
{
cout << "Array(size_t size)" << endl;
if (_size > 0)
{
_a = new int[size];
}
}
~Array()
{
cout << "~Array()" << endl;
if (_a)
{
delete[] _a;
_a = 0;
_size = 0;
}
}
private:
int* _a;
size_t _size;
};
void test()
{
// 1.malloc/free + 定位操作符new()/显⽰调⽤析构函数,模拟 new和delete 的⾏为
Array* p1 = (Array*)malloc(sizeof(Array));
new(p1) Array(100);
p1->~Array();
free(p1);
// 1.malloc/free + 多次调⽤定位操作符new()/显⽰调⽤析构函数,模拟 new[]和delete[]
//的⾏为
Array* p2 = (Array*)malloc(sizeof(Array) * 10);
for (int i = 0; i < 10; ++i)
{
new(p2 + i) Array;
}
for (int i = 0; i < 10; ++i)
{
p2[i].~Array();
}
free(p2);
}
int main()
{
test();
return 0;
}
运行结果如下:
6.delete[] 析构函数调用细节剖析
(1)new 首先调用operator new(),再调用malloc(),再调用构造函数,最后返回空间首地址。
(2)delete 首先调用析构函数,再调用operator delete(),最后free。
(3)new[] 显示定义析构函数时,会多开4个字节存储对象个数。首先调用operator new[],进而调用operator new(),malloc,构造函数(count次),返回首地址。
(4)delete[] 调用析构函数(count次),再调用operator delete[],operator delete(),最后free。
具体过程如下图所示: