C++ 的内存获取机制:
void* p1 = malloc(512);
free(p1);
complex<int>* p2 = new complex<int>;
delete p2;
void* p3 = ::operator new(512);
::operator delete(p3);
//GNUC
void* p4 = alloc::allocate(512);
alloc::deallocate(p4, 512);
//GNUC4.9
void* p5 = allocator<int>().allocate(7); //分配7个int
allocator<int>().deallocate((int*)p5, 7);
表达式 new delete
new的步骤:
- 申请一段指定类大小的空间:new —> operator new —> malloc
- 转化为对应类类型
- 调用类构造函数
在operator new的源码中,有个std::nothrow_t& _THROW0()参数,表示这个函数不抛异常,取而代之的是返回一个空指针,用户通过判断是否为空指针来判断是否分配成功。
array new、array delete
array new是分配一个对象数组,通常容易犯得一个错误是在delete的时候忘记在delete后面加[]导致内存泄漏的问题。
replacement new
允许我们将对象分配在已经构建的内存中
他不会进行内存分配,而是调用重载的operator new,用于返回已经分配好的内存,转型、调用构造函数。
#include<new>
char* buf = new char[sizeof(Complex)* 3];
Complex* pc = new(buf) Complex(1, 2); // replacement new!!!
Complex* pc = new Complex(1, 2);
函数operator new()、operator delete()
重载::operator new / ::operator delete
全局重载:
inline void* operator new(size_t size){
cout << "global new() " << endl;
return malloc(size);
}
inline void* operator new[](size_t size){
cout << "global new[]() " << endl;
return malloc(size);
}
在类中重载::operator new / ::operator delete更有用(array new / array delete重载也是一样的方法):
我们重载这两个函数,是为了接管内存分配的工作,接管它了有什么用呢?很有用,比如说可以做一个内存池(这个就是之前讲STL的时候的__pool_allocator):
为什么重载的operator new是static呢?因为希望实现的这个内存池是这个类的所有对象都能使用的!
我们可以重载operator new()的前提是:每一个版本的声明都必须有独特的参数列,其中第一个参数必须是size_t,其余参数以new所制定的replacement arguments为初值。
只有在上述的重载replacement new抛出异常的时候,才会调用相应的operator delete(这个需要自己去实现),因为在重载replacement new抛出异常,那么说明内存分配不成功,但是可能已经申请好内存,那么我们应该去处理申请好的这个内存。
static allocator
new handler
=default =delete
delete 我不要,default 使用默认的版本
std::allocator
参考文章:侯捷C++八部曲笔记(五、内存管理)_侯捷内存管理-CSDN博客