容器空间适配器allocator简单实现
大约 4 分钟
容器空间适配器allocator简单实现
容器为什么需要空间配置器,不用空间配置器会怎么样?
我们还是前面简单实现的vector容器,用Test来实例化:
class Test
{
public:
Test(){cout << "Test()" << endl;}
~Test(){cout << "~Test" << endl;}
};
对其进行实例化:
vector<Test> vec;
此时什么都没有做,这是一个空容器,但是却**。**,因此构造了10个对象,使用十分不合理。
问题分析:
①定义容器对象时,底层只是进行空间开辟,而不能去构造对象。但是如果使用new的话,它会同时完成这两件事。 ②析构时用了delete,将_first指针指向的数组每一个元素都当作有效的test对象析构了一遍。数组可能会很长,但是里面有效的元素可能只有几个,我们析构时只析构有效的元素,再将整个数组内存释放。
解决思路
①需要我们把与分开处理了。②析构容器有有效的元素,然后释放_first指针指向的堆内存。③只需要析构对象,将对象的析构和内存分离开。 此时就需要我们的容器空间配置器了。
allocator实现
容器的空间配置器allocator:容器底层内存开辟,内存释放,对象构造和析构,都通过allocator空间适配器来实现。
//容器的空间配置器
template <typename T>
struct Allocator
{
T* allocate(size_t size)//只负责内存开辟
{
return (T*)malloc(sizeof(T) * size);
}
void deallocate(void *p)//只负责内存释放
{
free(p);
}
void construct(T *p, const T &val)//已经开辟好的内存上,负责对象构造
{
new (p) T(val);//定位new,指定内存上构造val,T(val)拷贝构造
}
void destroy(T *p)//只负责对象析构
{
p->~T();//~T()代表了T类型的析构函数
}
};
template <typename T, typename Alloc = Allocator<T>>
class vector//向量容器
{
public:
vector(int size = 10)//构造
{
//_first = new T[size];
_first = _allocator.allocate(size);
_last = _first;
_end = _first + size;
}
~vector()//析构
{
//delete[]_first;
for (T *p=_first; p!=_last; ++p)
{
_allocator.destroy(p);//把_first指针指向的数组的有效元素析构
}
_allocator.deallocate(_first);//释放堆上的数组内存
_first = _last = _end = nullptr;
}
vector(const vector<T> &rhs)//拷贝构造
{
int size = rhs._end - rhs._first;//空间大小
//_first = new T[size];
_first = _allocator.allocate(size);
int len = rhs._last - rhs._first;//有效元素
for (int i=0; i<len; ++i)
{
//_first[i] = rhs._first[i];
_allocator.construct(_first+i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
}
vector<T>& operator=(const vector<T> &rhs)//赋值运算符重载
{
if (this == &rhs)
{
return *this;
}
//delete[]_first;
for (T *p=_first; p!=_last; ++p)
{
_allocator.destory(p);//把_first指针指向的数组的有效元素析构
}
_allocator.deallocate(_first);//释放堆上的数组内存
int size = rhs._end - rhs._first;//空间大小
_first = _allocator.allocate(size);
int len = rhs._last - rhs._first;//有效元素
for (int i=0; i<len; ++i)
{
_allocator.construct(_first+i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
return *this;
}
void push_back(const T &val)//尾插
{
if (full())
{
expand();
}
//*_last++ = val;
_allocator.construct(_last, val);//_last指针指向的内存构造一个值为val的对象
_last++;
}
void pop_back()//尾删
{
if (empty()) return;
//--_last;
//不仅要把_last指针--,还需要析构删除的元素
--_last;
_allocator.destroy(_last);
}
T back()const//返回容器末尾元素值
{
return *(_last - 1);
}
bool full()const
{
return _last == _end;
}
bool empty()const
{
return _first == _last;
}
int size()const//返回容器中元素个数
{
return _last - _first;
}
private:
T *_first;//起始数组位置
T *_last;//指向最后一个有效元素后继位置
T *_end;//指向数组空间的后继位置
Alloc _allocator;//定义容器的空间配置器对象
void expand()//扩容
{
int size = _end - _first;
//T *ptmp = new T[2*size];
T *ptmp = _allocator.allocate(2*size);
for (int i=0; i<size; ++i)
{
_allocator.construct(ptmp+i, _first[i]);
//ptmp[i] = _first[i];
}
//delete[]_first;
for (T *p=_first; p!=_last; ++p)
{
_allocator.destroy(p);
}
_allocator.deallocate(_first);
_first = ptmp;
_last = _first + size;
_end = _first + 2*size;
}
};
class Test
{
public:
Test(){cout << "Test()" << endl;}
~Test(){cout << "~Test" << endl;}
Test(const Test&){cout << "Test(const Test&)" << endl;}
};
int main()
{
Test t1, t2, t3;
cout << "-------------------------" << endl;
vector<Test> vec;
vec.push_back(t1);
vec.push_back(t2);
vec.push_back(t3);
cout << "-------------------------" << endl;
vec.pop_back();//只需要析构
cout << "-------------------------" << endl;
return 0;
}
