这里自己总结了自己对SGI的vector容器的操作原理的一点理解。
#ifndef _STL_VECTOR_H_
#define _STL_VECTOR_H_
template<class T, class Alloc=alloc>
class vector{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
protected:
//定义一个空间配置器,以元素大小为配置单位,也就是value_type类型的大小为配置单位
typedef simple_alloc<value_type, Alloc> data_allocator;
//目前使用空间的头
iterator start;
//目前使用空间的尾
iterator finish;
//目前可用空间的尾
iterator end_of_storage;
//负责释放空间
void deallocate()
{
if(start){
data_allocator::deallocate(start, end_of_storage - start);
}
}
//填充空间并且进行初始化
void fill_initialize(size_type n, const T& value)
{
start = allocate_and_fill(n, value);
finish = start + n;
end_of_storage = finish;
}
iterator allocate_and_fill(size_type n, const T& x)
{
iterator result = data_allocator::allocate(n);
uninitialized_fill_n(result, n, x);
return result;
}
//以下是vector容器提供的相应的接口,这里没有写全
public:
iterator begin(){return start;}//返回容器的起始位置
iterator end(){return finish;}//返回容器的结束位置
size_type size(){return size_type(end() - begin());}//使用空间的大小
//返回容器的大小
size_type capacity()const
{
return size_type(end_of_storage - begin());
}
bool empty()const{return begin() == end();}
//重载[]就可以进行下标的访问
reference operator[](size_type n){return *(begin() + n);}
public:
//5个构造函数的重载
vector():start(0),finish(0),end_of_storage(0){}
vector(size_type n, const T& value)
{
fill_initialize(n, value);
}
vector(int n, const T& value){fill_initialize(n, value);}
vector(long n, const T& value){fill_initialize(n, value);}
vector(size_type n){fill_initialize(n, T());}
~vector()
{
destroy(start, finish);
deallocate();
}
reference front(){return *begin();}//返回容器第一个元素的值
reference back(){return *(end() - 1);}
//尾插
void push_back(const T & x)
{
if(finish != end_of_storage){
construct(finish, x);
++finish;
}
//如果空间不足则调用insert_aux()
else{
insert_aux(end(), x);
}
}
//尾删,这里注意尾删只是将最后一个元素删除但是空间并没有释放
void pop_back()
{
--finish;
destory(finish);
}
//删除范围内的元素
iterator erase(iterator first, iterator last)
{
iterator i = copy(last, finish, first);
destory(i, finish);
finish = finish - (last - first);
return first;
}
//删除某个位置上的元素(将删除位置后面的元素直接往前移动覆盖掉要删除的元素即可)
iterator erase(iterator position)
{
if(position + 1 != end()){
copy(position + 1, finish, position);
}
--finish;
destory(finish);
return position;
}
//清空容器
void clear()
{
erase(begin(), end());
}
//插入
void insert(iterator position, size_type n, const T & x);
};
template<class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x)
{
if(finish != end_of_storage){
construct(finish, *(finish - 1));
++finish;
T x_copy = x;
copy_backward(position, finish - 2, finish - 1);
*position = x_copy;
}
//没有空间则扩充空间(申请新的空间大小为旧空间的2倍,拷贝元素到新空间,释放旧空间)
else{
const size_type old_size = size();
const size_type len = old_size != 0?2 * old_size : 1;
iterator new_start = data_allocator::allocate(len);
iterator new_finish = new_start;
new_finish = uninitialzed_copy(start, position, new_start);
construct(new_finish, x);
++new_finish;
new_finish = uninitialzed_copy(position, finish, new_finish);
}
destory(begin(), end());
deallocate();
start = new_start;
finish = new_finish;
end_of_storage = new_start + len;
}
//这里的插入操作分为2类
//(1)有足够的空间
// (1)判断插入的元素个数如果小于插入点之后的元素个数,先确定新的finish,然后再将插入
// 点后面的元素拷贝到old_finish,最后填充要插入的元素
// (2)插入的元素个数大于等于插入点之后的元素个数,先将要插入的元素的结束位置固定好,
// 然后将插入点以后的元素拷贝到之前固定好的结束位置处,最后填充要插入的元素
//(2)空间不足
template<class T, class Alloc>
void vector<T, Alloc>::insert(iterator position, size_type n, T& x)
{
if(n != 0){
if(n < (size_type)(end_of_storage - finish)){
T x_copy = x;
const size_type elems_after = finish - position;
iterator old_finish = finish;
if(elems_after > n){
uninitialized_copy(finish - n, finish, finish);
finish += n;
copy_backward(position, old_finish - n, old_finish);
fill(position, position + n, x_copy);
}
else{
uninitialized_fill_n(finish, n - elems_after, x_copy);
finish += n - elems_after;
uninitialized_copy(position, old_finish, finish);
finish += elems_after;
fill(position, position + n, x_copy);
}
}
else{
const size_type old_size = size();
const size_type len = old_size != 0?2*old_size:1;
iterator new_start = data_allocator::allocate(len);
iteratoe new_finish = new_start;
new_finish = uninitialized_copy(start, position, new_start);
new_finish = uninitialized_fill_n(new_finish, n, x);
new_finish = uninitialized_copy(position, finish, new_finish);
destory(start, finish);
deallocate();
start = new_start;
finish = new_finish;
end_of_storage = finish + len;
}
}
}
#endif