這裏自己總結了自己對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