空间置配器allocator
placement new 与 new
new关键字操作:
- 调用operator new为对象申请内存
- 在申请到的内存地址上调用对象的构造函数
- 返回对象的地址
placement new的作用不是开辟新内存,是在指定内存块上构造对象。
举例
class A {...};
class B {...};
A* pa = new A;
pa->~A();
B* pb = new (pa) B; //sizeof(B) <= sizeof(A)
在上面的代码中,pb并没有指向一块新开辟的内存,而是重用了pa指向的内存。直接在pa指向的内存上调用B的构造函数。
目的
placement new复用原有内存块,可以减小内存分配回收的开销。
构造与析构
constructor
- 接受一个指针p和一个初值value,调用了placement new
- new(p) T(value)
destory
- 接受一个指针,析构其指向的对象
- 直接调用析构函数
- 接受first,last两个迭代器,将[first, last)内的对象析构
- trivial destory:no-op
- non-trivial destory:遍历每个对象并调用destory
- 目的:减少trivial destory的开销。
空间的配置与释放
双层级配置器
- 第一级配置器
- 直接使用malloc(),free()
- 模拟C++的set_new_handler()以处理内存不足的状况。
- 第二级配置器
- 当配置区超过128bytes,调用第一级配置器
- 当配置区小于128bytes,采用自由链表(free list)+内存池(memory pool)处理。16个自由链表负责16个小型区块的次配置能力。内存池以malloc()配置而得。如果内存不足,转调用第一级配置器(那有处理程序)。
set_new_handler
函数原型:
std::new_handler set_new_handler( std::new_handler new_p )
当allocator空间分配失败时,调用new_handler函数,如果函数返回null pointer value,则抛出bad_alloc异常
内存基本处理工具
五个全局函数,作用于未初始化空间:
- ctor
- dtor
- uninitialized_copy
- 特化:
- char:memmove()
- wchar:memmove()
- 泛化:
- non-POD:construct()
- POD:copy()
- 特化:
- uninitialized_fill
- non-POD:construct()
- POD:fill()
- uninitialized_fill_n
- non-POD:construct()
- POD:fill_n()
Plain Old Data, POD
POD型别必然有trivial ctor/dtor/copy/assignment函数,如标量型别(scalar types)或传统的C struct型别
因此对POD型别采取最高效率的方法,对non-POD采用最安全的方法