您的位置:首页 > 其它

vector

2016-05-02 13:46 369 查看
看完STL源码剖析也有2个月了吧,虽然看的时候明白了,但很快就忘了,Vector更是看过好几次了,但都没有记录下来。

还是从开头开始吧,毕竟现在只是打地基,打地基,打地基~.~

vector是个动态空间(array是静态空间)

所以实现vector关键在于其对大小的控制以及重新配置时的数据移动效率

对于扩充空间(不论大多),是“配置新空间/ 数据移动 / 释还旧空间”的大工程,时间成本很高,所以空间配置策略很重要

1. vector定义摘要

对于 simple_alloc ,看了一遍还不是很清楚,下篇写它了

下面代码的整体结构

类名
public:
vector的嵌套型别定义(我的理解:方面后用用到这些类型)

protected:
simple_alloc 是SGI STL的空间配置器
typedef simple_alloc<value_type, Alloc> data_allocator;

列出表示空间各个部位的迭代器
iterator start;
iterator finish;
iterator end_of_storage;

列出插入函数的声明
void insert_aux (iterator position, const T& x);

void deallocate()
void fill_initialize(size_type n, const T& value)

public:
结合上述的给出的空间适配器中的属性来定义vector的各种简单函数
begin().end().size(),capacity(),empty(),operator[]

以及vector的构造函数
vector()
vector(size_type n, const T& value)
vector(int n, const T& value)
vector(long n, const T& value)
explicit vector(size_type n)

所有的构造函数都用fill_initialize()来实现

析构函数 ~vector()

reference front()
reference back()
void push_back(const T& x)
void pop_back()
iterator erase(iterator position)

void resize(size_type new_size, const T& x)
void resize (size_type new_size)

protected:
配置空间并填满内容
iterator allocate_and_fill(size_type n, const T& x)


class vector
{
public:

//vector 的嵌套型别定义
typedef T           value_type;
typedef value_type* pointer;
typedef value_type* iterator;
typedef value_type& reference;
typedef size_t      size_type;
typedef ptrdiff_t*  difference_type;

protected:
//以下,simple_alloc 是SGI STL的空间配置器
typedef simple_alloc<value_type, Alloc> data_allocator;
iterator start;             //表示目前使用空间的头
iterator finish;            //表示目前使用空间的尾
iterator end_of_storage;    //表示目前可用空间的尾

void insert_aux (iterator position, const T& x);
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;
}

public:
iterator begin() {return start;}
iterator end()   {return finish;}
size_type size() const {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); }

//构造函数,允许指定vector大小n和初值value

vector(): start(0), finish(0), end_of_storage(0) {}
vector(size_type n, const T& value) {f ill_initialize(n,value); }
vector(int n, const T& value) { fill_initialize(n,value); }
vector(long n, const T& value) { fill_initialize(n,value); }
explicit vector(size_type n) { fill_initialize(n,T()); }

~vector()
{
destroy (start, finish);    //全局函数 ,见2.2.3
deallocate();               //这是vector的一个member function
}

reference front() {return *begin();}    //第一个元素
reference back() { return *(end()-1);}  //最后一个元素
void push_back(const T& x)              //将元素插入至最尾端
{
if(finish != end_of_storage)        //还有备用空间
{
construct(finish,x);            //全局函数,见2.2.3
++finish;                       //调整水位高度  这里只构造了一个空间,所以++
}
else                                //已经没有备用空间
insert_aux(end(),x);            //这是vector的一个Member function
}

void pop_back()                     //将最尾端元素取出
{
--finish;
destroy(finish);                //全局函数,见2.2.3
}

iterator erase(iterator position)   //清除某位置上的元素
{
if(position + 1 != end())
copy(position+1, finish, position); //后续元素往前移动
--finish;
destroy(finish);                //全局函数,见2.2.3
return position;
}

void resize(size_type new_size, const T& x)
{
if(new_size < size())
erase(begin() + new_size, end());
else
insert(end(), new_size-size(), x);
}

void resize (size_type new_size) {resize(new_size, T()); }
void clear() {erase(begin(), end());}

protected:
//配置空间并填满内容
iterator allocate_and_fill(size_type n, const T& x)
{
iterator result - data_allocator::allocate(n);  //配置N个元素空间
uninitialized_fill_n(result, n, x); //全局函数,见2.3
//会根据第一参数的型别特性(type trail 3.7节),决定使用算法fill_n()或反复调用construc()来完成任务
return result;
}
}

};


vector提供的是Random Access Iterators

vector的数据结构



2.vector的构造与内存管理 constructor, push_back

这里的constructor由上面已经一定义的这俩个函数执行
void fill_initialize(size_type n, const T& value)
iterator allocate_and_fill(size_type n, const T& x)


然后是PUSH_BACK()
用insert_aux()函数表示,其中不仅包含insert还包含在没有空间状态下的push_back()
这里是插入一个元素


//push_back
template<class T, class Alloc>
void vector<T,Alloc>::insert_aux(iterator position, const T& x)
{
if(finish != end_of_storage)  //还有备用空间
{
//在备用空间起初始处构造一个元素,并以vector最后一个元素值为其初值
construct(finish, *(finish-1));
//调整水位;
++finish;
T x_copy = x;
copy_backward(position , finish-2, finish-1);  //这里是插入,所有,要复制之前后的元素移位
*position = x_copyt;
}
else   //已无备用空间
{
const size_type old_size= size();
const size_type len = old_size != 0 ? 2*old_size : 1;
//以上配置原则:如果原大小为0,则配置1(个元素大小);
//如果原大小不为0,则配置原大小的俩倍
//前半段用来放置原数据,后半段准备用来放置新数据

iterator new_start = data_allocator::allocate(len); //实际配置
iterator new_finish = new_start;
try
{
//将原vector的内容拷贝到新vector
new_finish = uninitialized_copy(start,position, new_start);
//为新元素设定初值X
construct(new_finish,x);
//调整水位
++new_finish;
//将安插点的原内容也拷贝过来(提示:本函数也可能被insert(p,x)调用 //如果被insert(p,x)调用的时候,前面只是把VECTOR的前半部分复制,下面是赋值后半部分
new_finish = uninitialized_copy(position, finish ,new_finish);
}
catch(...)
{
//"commit or rollback" semantics
destroy(new_start, new_finish);
data_allocator::deallocate(new_start, len);
throw;
}

//析构并释放原vector
destroy(begin(),end());
deallocate();

//调正迭代器,指向新vector
start = new_start;
finish = new_finish;
end_of_storage = new_satrt + len;
}
}


3.vector的元素操作 pop_back,erase, clear, insert

这里的insert是插入几个连续的相同大小的元素
其中Insert用的方法不是不简单的整体移动,而是分成俩部分,现在还不知道其中原因,但是觉得很神奇。。   //!有时间再探讨


//将尾端元素拿掉,并调整大小
void pop_back()
{
--finish;
destroy(finish);  //destroy是全局函数,见第2章
}

//清除[first, last)中的所有元素
iterator erase(iterator first, iterator last)
{
iterator i = copy(last, finish , first);  //copy是全局函数,第6章
destroy(i,finish);                         //destroy是全局函数,第2章
finish = finish - (last - first);
return first;
}

//清除某个位置上的元素
iterator erase (iterator position)
{
if(position + 1 != end())                 //不是最后一个元素
copy(postion+1, finish, position);    //copy是全局函数,第6章
--finish;
destroy(finish);                          //destroy是全局函数,第2.2.3
return position;
}

void clear()
{
erase(begin(),end());
}

//从position 开始,插入N个元素,元素初值为X
template<class T, class Alloc>
void vector<T,Alloc> :: insert(iterator position, size_type n, const T& x)
{
if (n!=0)
{
if(size_type(end_of_storage - finish) >= n)         //备用空间大于等于“新增元素个数”
{
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, old_finish, x_copy);         //神奇!!!!!
}
}

else
{
//备用空间小于“新增元素个数” (那就必须配置额外的内存)
//首先决定新的长度:旧长度的俩倍,或 旧长度+新增元素的个数
const size_type old_size = size();
const size_type len = old_size +max(old_size, n);

//以下配置新的vector空间
iterator new_start = data_allocator::allocate(len);
iterator new_finish = new_start;

_STL_TRY
{
//以下首先将旧vector的插入点之前的元素复制到新空间
new_finish = uninitialized_copy(start,position,new_start);
//以下再将新增元素(初值皆为N)填入新空间
new_finish = uninitialized_fill_n(new_finish,n,x);
//以下再将旧vector的插入点之后的元素复制到新空间
new_finish = uninitialized_copy(positon, finish , new_finish);

}

#ifdef _STL_USE_EXCEPTIONS
catch(...)
{
//如果有异常发生,实现“commit or rollback” semantics
destroy(new_start, new_finish);
data_allocator::deallocate(new_start, len);
throw;
}
#endif // _STL_USE_EXCEPTIONS

//以下清除并释放旧的vector
destroy(start, finish);
deallocate();
//以下调整水平标记
start = new_start;
finish = new_finish;
end_of_storage = new_start +len;

}
}
}


经过梳理,对vector清晰了很多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: