目录
Allocator:对容器与内存分布进行管理的承担者

- #include
- #include
- #include
- #include
- using namespace std;
-
- //空间配置器的基类模板
- template<class _Ty>
- struct Allocator_base {
- typedef _Ty value_type;
- };
-
- template<class _Ty>
- struct Allocator_base<const _Ty> {
- typedef _Ty value_type;
- };
-
- //空间配置器的类模板设计
- template<class _Ty>
- class Allocator :public Allocator_base<_Ty> {
- public:
- //内嵌数据类型表
- typedef typename std::size_t size_type;
- typedef typename std::ptrdiff_t difference_type;
- typedef _Ty* pointer;
- typedef const _Ty* const_pointer;
- typedef _Ty& reference;
- typedef const _Ty& const_reference;
- typedef Allocator_base<_Ty> _Mybase;
- typedef typename _Mybase::value_type value_type;
-
- //配置器类型的嵌入类型
- template<class _U>
- struct rebind {
- typedef Allocator<_U>other;
- };
-
- //构造函数
- Allocator()throw() {
-
- }
- Allocator(const Allocator&)throw() {}
-
- //可以接受不同类型的其他allocator的拷贝构造
- template<class _otherAll>
- Allocator(const Allocator<_otherAll>&)throw() {}
-
- ~Allocator()throw()
- {
-
- }
-
- //请求内存空间
- pointer allocate(size_type num, typename Allocator<_Ty>::const_pointer hint = 0) {
- //显示一下内存空间发呢配信息
- static int i = 0;
- i++;
- cout << endl;
- cout << "第" << i << "次分配" << "-----------------------" << endl;
- cout << "本次需要分配可容纳" << num << "个元素空间" << endl;
- return (pointer)(::operator new(num * sizeof(_Ty)));
- }
-
- //在已经请求的内存空间中构造容器元素对象:operator new之后,用placement new指向
- void construct(pointer p, const_reference value) {
- new(p)_Ty(value);
- }
-
- //析构容器元素对象
- void destroy(pointer p) {
- p->~_Ty();
- }
-
- //释放已有的内存空间
- void deallocate(pointer p, size_type size) {
- ::operator delete(p);
- }
-
- };
-
- //调用
- template<typename _T>
- void print(vector<_T, Allocator<_T>>& iv) {
- cout << "现在空间可容纳" << iv.capacity() << "个元素";
- cout << "\t 容器当前所存储元素数目:" << iv.size() << endl;
- cout << "容器中的元素数据:";
- for_each(iv.begin(), iv.end(), [](int n) {cout << " " << n; });
- cout << endl;
- }
-
- int main() {
- int a[] = { 1,2,3 };
- vector<int, Allocator<int>>vec(a, a + 3);
- print<int>(vec);
- for (int i = 1; i < 10; i++) {
- vec.push_back(10 * i);
- print<int>(vec);
- }
- return 0;
- }

可以看到每次分配的内存空间均为上次的1.5倍,这也是VS编译器所采取的策略。
不同C++编译器分配内存策略不同,例如g++就是2倍。
对之前的代码做以下修改,变为list的,其他代码保持不变:
- //调用
- template<typename _T>
- void print(list<_T, Allocator<_T>>& iv) {
- //cout << "现在空间可容纳" << iv.capacity() << "个元素";
- cout << "\t 容器当前所存储元素数目:" << iv.size() << endl;
- cout << "容器中的元素数据:";
- for_each(iv.begin(), iv.end(), [](int n) {cout << " " << n; });
- cout << endl;
- }
-
- int main() {
- int a[] = { 1,2,3 };
- //vector
>vec(a, a + 3); - list<int, Allocator<int>>myList(a, a + 3);
- print<int>(myList);
- for (int i = 1; i < 5; i++) {
- myList.push_back(10 * i);
- print<int>(myList);
- }
- return 0;
- }

可以看到list的分配内存方式是一个一个分配的,需要一个就分配一个,不留余量。
- //调用
- template<typename _T>
- void print(deque<_T, Allocator<_T>>& iv) {
- //cout << "现在空间可容纳" << iv.capacity() << "个元素";
- cout << "\t 容器当前所存储元素数目:" << iv.size() << endl;
- cout << "容器中的元素数据:";
- for_each(iv.begin(), iv.end(), [](int n) {cout << " " << n; });
- cout << endl;
- }
-
- int main() {
- int a[] = { 1,2,3 };
- //vector
>vec(a, a + 3); - //list
>myList(a, a + 3); - deque<int,Allocator<int>>deq(a, a + 3);
- print<int>(deq);
- for (int i = 1; i < 200; i++) {
- deq.push_back(i);
- //print
(deq); - }
- return 0;
- }

deque每次分配固定大小内存,每次4个,逐次累加。



- #include
- #define MEMPOOL_ALIGNMENT 8
- using namespace std;
-
- //内存块
- template<typename _T>
- struct MemoryBlock{
- //表域
- int nSize;//内存块大小,以字节为单位
- int nFree;//表示内存剩余可分配的单位
- int nFirst;//首个剩余单位的序号
-
- MemoryBlock* pNext;
- char aData[1];//内存空间开始位置标记
-
-
- MemoryBlock(int nUnitSize, int nUninAmount) :
- nSize(nUnitSize* nUninAmount), nFree(nUninAmount - 1), nFirst(1), pNext(nullptr)
- {
- //下一个可以分配的单位序号需要记录当前单元的强两个字节
- char* ppData = aData;
- cout << "存储区首地址ppData=" << (int)*ppData << endl;
- for (int i = 1; i < nUninAmount; i++) {
- //在当前存储单位空间 存储下一个可分配的单位序号
- (*(unsigned short*)ppData) = i;
- ppData += nUnitSize;
- }
- cout << "内存块的构造函数被调用了" << endl;
- }
-
- //nUnitSize:存储单位大小
- //nUnitAmount:内存块的规模(数量)
- void* operator new(size_t, int nUnitSize, int nUnitAmount) {
- cout << "分配内存空间并创建MemoryBlock" << endl;
- return ::operator new(sizeof(MemoryBlock) + nUnitSize * nUnitAmount);
- }
-
- void operator delete(void* pBlock) {
- cout << "调用了内存的析构" << endl;
- }
- };
-
- //内存池 Mempool
- template<typename _T>
- struct MemoryPool
- {
- int nInitSize;
- int nGrowSize;
- int nUnitSize;
- MemoryBlock<_T>* pBlock;
-
- MemoryPool(int _nGrowSize = 10, int _nInitSize = 3) {
- cout << "调用了内存池的构造函数" << endl;
- nInitSize = _nInitSize;
- nGrowSize = _nGrowSize;
-
- pBlock = nullptr;
- nUnitSize = (sizeof(_T));
-
- //纯出单位的大小调整
- if (sizeof(_T) > 4) {
- //8字节对齐
- nUnitSize = (sizeof(_T) + (MEMPOOL_ALIGNMENT - 1)) &
- ~(MEMPOOL_ALIGNMENT - 1);
- }
- else {
- if (sizeof(_T) < 2) { nUnitSize = 2; }
- else { nUnitSize = 4; }
- }
- }
-
- ~MemoryPool() {
- MemoryBlock<_T>* pMyBlock = pBlock;
- while (pMyBlock != nullptr) {
- pMyBlock = pMyBlock->pNext;
- delete(pMyBlock);
- }
- cout << "调用了内存池的析构函数" << endl;
- }
-
- void* allocate(size_t num) {
- for (int i = 0; i < num; i++) {
- if (pBlock == nullptr) {
- //创建首个内存块
- pBlock = (MemoryBlock<_T>*)new(nUnitSize, nInitSize)MemoryBlock<_T>(nUnitSize, nInitSize);
- return (void*)pBlock->aData;
- }
- //为内存寻求合适的内存块
- MemoryBlock<_T>* pMyBlock = pBlock;
- while (pMyBlock != nullptr && pMyBlock->nFree == 0) {
- pMyBlock = pMyBlock->pNext;
- }
- if (pMyBlock != nullptr) {
- cout << "内存空间已经找到,First=" << pMyBlock->nFirst << endl;
- char* pFree = pMyBlock->aData + pMyBlock->nFirst * nUnitSize;
- pMyBlock->nFirst = *((unsigned short*)pFree);
- pMyBlock->nFree--;
- return (void*)pFree;
- }
- else {
- //说明内存用完了
- if (nGrowSize == 0) {
- return nullptr;
- }
- cout << "分配新内存" << endl;
- pMyBlock = (MemoryBlock<_T>*)new (nUnitSize, nGrowSize)MemoryBlock<_T>(nUnitSize, nGrowSize);
-
- if (pMyBlock == nullptr) {
- return nullptr;
- }
- //如果成功那么,将新内存插入链表
- pMyBlock->pNext = pBlock;
- pBlock = pMyBlock;
- return (void*)pMyBlock->aData;
- }
- }
- }
-
- void free(void* pFree) {
- cout << "释放存储单位的空间" << endl;
- //找到p所在的内存块
- MemoryBlock<_T>* pMyBlock = pBlock;
- MemoryBlock<_T>* PreBlock = nullptr;
-
- while (pMyBlock != nullptr && (pBlock->aData > pFree)
- || pMyBlock->aData + pMyBlock->nSize) {
- PreBlock = pMyBlock;
- pMyBlock = pMyBlock->pNext;
- }
-
- //该内存在本内存池中的指向位置
- if (pMyBlock != nullptr) {
- //修改数组链表
- *((unsigned short*)pFree) = pMyBlock->nFirst;
- pMyBlock->nFirst = (unsigned short)((unsigned long)pFree - (unsigned long)pMyBlock->aData) / nUnitSize;
- pMyBlock->nFree++;
-
- //判断是否需要向操作系统释放内存
- if (pMyBlock->nSize == pMyBlock->nFree * nUnitSize) {
- delete(pMyBlock);
- }
- else {
- PreBlock = pMyBlock->pNext;
- pMyBlock->pNext = pBlock;
- pBlock = pMyBlock;
- }
- }
- }
- };
-
- class UserCls {
- int s;
- double s1;
- double s2;
- public:
- UserCls(int x) :s(x) {
- cout << "调用了UserCls的构造函数" << endl;
- }
- int get() { return s; }
- ~UserCls()
- {
- cout << "调用了UserCls的析构函数" << endl;
- }
- };
-
- int main() {
- MemoryPool
M_Pool; -
- UserCls* dp1 = (UserCls*)M_Pool.allocate(1);
- cout << "dp1=" << dp1 << endl;
- new(dp1)UserCls(111);
- cout << "dp1中的数据是" << dp1->get() << endl;
- cout << endl;
-
- UserCls* dp2 = (UserCls*)M_Pool.allocate(1);
- cout << "dp2=" << dp2 << endl;
- new(dp2)UserCls(222);
- cout << "dp2中的数据是" << dp2->get() << endl;
- cout << endl;
-
- UserCls* dp3 = (UserCls*)M_Pool.allocate(1);
- cout << "dp3=" << dp3 << endl;
- new(dp3)UserCls(333);
- cout << "dp3中的数据是" << dp3->get() << endl;
- cout << endl;
-
- UserCls* dp4 = (UserCls*)M_Pool.allocate(1);
- cout << "dp4=" << dp4 << endl;
- new(dp4)UserCls(444);
- cout << "dp4中的数据是" << dp4->get() << endl;
- cout << endl;
-
- UserCls* dp5 = (UserCls*)M_Pool.allocate(1);
- cout << "dp5=" << dp5 << endl;
- new(dp5)UserCls(555);
- cout << "dp5中的数据是" << dp5->get() << endl;
- cout << endl;
-
- return 0;
- }
