1. 介绍
一般情况下,将内存分配和对象构造组合在一起可能会导致不必要的浪费(有些对象可能用不了那么多的内存)。在此情况下,我们希望将内存分配和对象构造分离。这意味着我们可以按需分配内存,但只在真正需要时才真正执行对象的内存扩充操作(同时付出一定开销)。常见的容器vector的内存分配就是这种方案。
- 标准库allocator类定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来。
2. 主要成员函数
- allocate
pointer allocate(size_type n);
分配存储块;尝试分配n个T个类型的存储空间,然后返回第一个元素的起始地址;只分配空间,不构造对象
- construct
void construct(U* p, T a);
在p所指内存中构造一个T类型的对象a
- destory
void destroy (T* p);
调用析构函数销毁p所指的对象,但不会释放空间,也就意味着,这段空间依然可以使用
- deallocate
void deallocate(pointer p, size_t n);
释放先前allocate分配的且没有被释放的存储空间,意味着回收空间
p:指向以前使用allocator :: allocate分配的存储块的指针。
n:在调用allocator :: allocate时为这个存储块分配的元素数量。
3. 使用步骤
- allocator与类绑定,因为allocator是一个泛型类
- allocate()申请指定大小空间
- construct()构建对象,其参数为可变参数,所以可以选择匹配的构造函数
- 使用,与其它指针使用无异
- destroy()析构对象,此时空间还是可以使用
- deallocate()回收空间
4. 实例使用
- m_vector.h
#include<iostream>
#include<memory>
using std::cout;
using std::endl;
template<typename Tp>
class Vector
{
public:
Vector():_elems(NULL),_first_free(NULL),_end(NULL){}
~Vector()
{
if(_elems){
while(_elems!=_first_free)
_alloc.destroy(--_first_free);
_alloc.deallocate(_elems,capacity());
}
}
void push_back(const Tp& value)
{
if(size()==capacity())
reallocate();
_alloc.construct(_first_free++,value);
}
void pop_back()
{
if(size()>0)
{
_alloc.destory(--_first_free);
}
}
size_t size() const
{
return _first_free-_elems;
}
size_t capacity() const
{
return _end-_elems;
}
Tp & operator[](size_t idx)
{
return _elems[idx];
}
private:
static std::allocator<Tp> _alloc;
Tp* _elems;
Tp* _first_free;
Tp* _end;
void reallocate()
{
size_t oldCapacity=capacity();
size_t newCapacity = oldCapacity==0?1:oldCapacity*2;
Tp* newElems=_alloc.allocate(newCapacity);
if(_elems){
std::uninitialized_copy(_elems,_first_free,newElems);
while(_elems!=_first_free)
_alloc.destroy(--_first_free);
_alloc.deallocate(_elems,oldCapacity);
}
_elems=newElems;
_first_free=_elems+oldCapacity;
_end=_elems+newCapacity;
}
};
template<typename Tp>
std::allocator<Tp> Vector<Tp>::_alloc; //构造实例
void display(Vector<int> & vec)
{
cout<<"vec's size= "<<vec.size()<<endl;
cout<<"vec's capacity= "<<vec.capacity()<<endl;
}
- main.cpp
#include<iostream>
#include"m_vector.h"
using std::cout;
using std::endl;
int main(int argc,char** argv)
{
Vector<int> VecInt;
display(VecInt);
VecInt.push_back(1);
display(VecInt);
VecInt.push_back(2);
display(VecInt);
VecInt.push_back(3);
display(VecInt);
VecInt.push_back(4);
display(VecInt);
VecInt.push_back(5);
display(VecInt);
VecInt.push_back(6);
display(VecInt);
VecInt.push_back(7);
display(VecInt);
for(size_t idx=0;idx!=VecInt.size();++idx)
{
cout<<VecInt[idx]<<" ";
}
cout<<endl;
}