C++ 侯捷 内存管理

C++ 的内存获取机制:

C++ 侯捷 内存管理_第1张图片C++ 侯捷 内存管理_第2张图片

void* p1 = malloc(512);
free(p1);

complex* p2 = new complex;
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().allocate(7); //分配7个int
allocator().deallocate((int*)p5, 7);

表达式 new delete

C++ 侯捷 内存管理_第3张图片

new的步骤:

  1. 申请一段指定类大小的空间:new —> operator new —> malloc
  2. 转化为对应类类型
  3. 调用类构造函数

在operator new的源码中,有个std::nothrow_t& _THROW0()参数,表示这个函数不抛异常,取而代之的是返回一个空指针,用户通过判断是否为空指针来判断是否分配成功。

array new、array delete

C++ 侯捷 内存管理_第4张图片

array new是分配一个对象数组,通常容易犯得一个错误是在delete的时候忘记在delete后面加[]导致内存泄漏的问题。

replacement new

C++ 侯捷 内存管理_第5张图片

允许我们将对象分配在已经构建的内存中

他不会进行内存分配,而是调用重载的operator new,用于返回已经分配好的内存,转型、调用构造函数。

#include
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

C++ 侯捷 内存管理_第6张图片

全局重载:

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重载也是一样的方法):

C++ 侯捷 内存管理_第7张图片

C++ 侯捷 内存管理_第8张图片 

我们重载这两个函数,是为了接管内存分配的工作,接管它了有什么用呢?很有用,比如说可以做一个内存池(这个就是之前讲STL的时候的__pool_allocator)

为什么重载的operator new是static呢?因为希望实现的这个内存池是这个类的所有对象都能使用的!

我们可以重载operator new()的前提是:每一个版本的声明都必须有独特的参数列,其中第一个参数必须是size_t,其余参数以new所制定的replacement arguments为初值。
C++ 侯捷 内存管理_第9张图片

只有在上述的重载replacement new抛出异常的时候,才会调用相应的operator delete(这个需要自己去实现),因为在重载replacement new抛出异常,那么说明内存分配不成功,但是可能已经申请好内存,那么我们应该去处理申请好的这个内存。

static allocator

C++ 侯捷 内存管理_第10张图片

C++ 侯捷 内存管理_第11张图片

C++ 侯捷 内存管理_第12张图片

new handler

C++ 侯捷 内存管理_第13张图片

C++ 侯捷 内存管理_第14张图片 

=default   =delete

delete 我不要,default  使用默认的版本

C++ 侯捷 内存管理_第15张图片

std::allocator

参考文章:侯捷C++八部曲笔记(五、内存管理)_侯捷内存管理-CSDN博客 

你可能感兴趣的:(C++,c++)