假定你现在已经能熟练使用vector,如果你很好奇vector背后是怎么实现的,那么本文或许对你能有所帮助。
vector代表了c++的动态数组,大小是动态可增长的。你不必考虑自己手动分配或释放内存,也不必担心内存泄漏,vector帮你做了这一切。vector的使用很简单,但是要做到有效率,没那么容易,了解他背后的实现原理能帮助达到这一目的。
言归正传。本文基于SGI STL的一个vector的实现,向大家讲述vector的实现思想和技术,如有不妥的地方,还请大家给出批评建议。(建议大家在阅读本文之前,先能温习一下vector的相关内容和用法)。
让我们先看看类的声明和数据成员:
#include <alloc.h> //内存分配器头文件,非标准
#include <iterator.h> //迭代器头文件,非标准
template <class T > //模板类声明,提供泛型功能。
class vector {
typedef alloc Alloc; //内存分配器typedef
public:
typedef T value_type; //值类型 T
typedef value_type* pointer; // 指针类型 T*
typedef value_type* iterator; //迭代器,这里的迭代器不需要封装,只是一个原生指针的typedef
typedef const value_type* const_iterator; // 只读迭代器
typedef value_type& reference; //引用 T&
typedef const value_type& const_reference; //只读引用
typedef size_t size_type; //长度类型 size_t,一般是unsigned int;
typedef ptrdiff_t difference_type; // 指针间隔,用来表示两个指针间的距离
typedef reverse_iterator<const_iterator, value_type, const_reference,
difference_type> const_reverse_iterator; //反向迭代器,定义在<iterator.h>
typedef reverse_iterator<iterator, value_type, reference, difference_type>
reverse_iterator; //只读反向迭代器
protected:
//数据成员
typedef simple_alloc<value_type, Alloc> data_allocator; //分配器的typedef
iterator start; //vector的第一个元素的迭代器,用来表示vector,永远为vector.begin();
iterator finish; //vector的末尾,指向vector的最后一个元素的下一个位置。永远为vector.end();
iterator end_of_storage; //vector所拥有的内存的末尾。如果等于vector.end(),表示vector已满
}
从以上我们可以看到,vector用allocator来进行内存管理,用三个迭代器来引用这段内存。vector的iterator 其实就是T*的别名。我们知道在一个连续的内存里(数组),指针是可以做算术运算的,也支持[]操作,所以vector的iterator也支持算术运 算,++,--,+=, -=,[],vector的迭代器就是通常的随机访问迭代器了。
另外,我想说的是,STL有许多流行的版本,每一个版本实现都不是相同的,但是原理区别不大。vector的底层实现一般是连续的内存(数组)。 deque的实现是连续的内存块,list的是双链表,set和map是红黑树。stack和queue都是这些容器的适配器(用这些容器来实现)。知道 这些是很有必要的。
下一篇文章里,将会讨论到vector的常用接口的实现。
上一篇我们讨论了vector的声明,接下来您将看到的是vector的接口和实现。
class vector {
public:
...
iterator begin() { return start; } //返回vetor的首
const_iterator begin() const { return start; } //只读访问
iterator end() { return finish; } //返回vector的末尾
const_iterator end() const { return finish; } //只读访问
reverse_iterator rbegin() { return reverse_iterator(end()); } //反向迭代器
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
} //只读访问
reverse_iterator rend() { return reverse_iterator(begin()); } //反向迭代器
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
size_type size() const { return size_type(end() - begin()); } //size,vector的长度
size_type max_size() const { return size_type(-1); } //vector支持的最大长度,4294967295
size_type capacity() const { return size_type(end_of_storage - begin()); } //vector的当前 容量.表示当前的vector有多大的容量。
bool empty() const { return begin() == end(); } //判断vetor是否为空,实现保证这个函数永远是常量时间复杂度。判断vector为空间已用empty,不要用size()==0,因为 size()有可能是线性时间复杂度。
reference operator[](size_type n) { return *(begin() + n); } // []操作符
const_reference operator[](size_type n) const { return *(begin() + n); } //只读
vector() : start(0), finish(0), end_of_storage(0) {} //默认构造函数
vector(size_type n, const T& value) { //初始化长度为n,每个值均为value的vetor
start = data_allocator::allocate(n); //vector的内存分配委托给allocator来实现
iterator first = start;
while(n--)
{
*first++ = value;
}
finish = start + n;
end_of_storage = finish;
}
vector(size_type n) { //初始化长度为n,每个值均为默认值的vector
start = data_allocator::allocate(n);
while(n--)
{
*first++ = T();
}
finish = start + n;
end_of_storage = finish;
}
vector(const vector<T /*, Alloc*/>& x) { //拷贝构造函数
start = data_allocator::allocate(x.end() - x.begin());
finish = start;
for(iterator i = x.begin(); i != x.end(); ++i )
{
*finish++ = *i;
}
end_of_storage = finish;
}
vector(const_iterator first, const_iterator last) { //迭代器构造函数
size_type n = 0;
distance(first, last, n); //判断first到last的距离
start = data_allocator::allocate(n);
finish = start;
for(iterator i = x.begin(); i != x.end(); ++i )
{
*finish++ = *i;
}
end_of_storage = finish;
}
~vector() { //vector的析构函数
destroy(start, finish); //调用每个元素的析构函数
deallocate(); //释放vector的内存
}
vector<T /*, Alloc*/>& operator=(const vector<T /*, Alloc*/>& x);
void reserve(size_type n) { //vector的reverse函数,主要是用作vector的扩容,增加vector的容量到 n所制定的大小。为了防止vector发生过多的插入拷贝,建议用此函数为vector申请足够大的容量
if (capacity() < n) {
const size_type old_size = size();
const iterator tmp = data_allocator::allocate(n);
uninitialized_copy(begin(), end(), tmp);
destroy(start, finish);
deallocate();
start = tmp;
finish = tmp + old_size;
end_of_storage = start + n;
}
}
reference front() { return *begin(); } //返回vector的第一个元素
const_reference front() const { return *begin(); } //
reference back() { return *(end() - 1); } //返回vector的最后一个元素
const_reference back() const { return *(end() - 1); }
void push_back(const T& x) { //vector的push_back,最常用的函数,想vector的末尾增加值
if (finish != end_of_storage) {
*finish = x;
++finish;
} else
insert_aux(end(), x); //如果vector容量已满,进行插入。
}
void swap(vector<T /*, Alloc*/>& x) { //交换两个vector的值.这个是很有效率的。常量时间交换。
::swap(start, x.start);
::swap(finish, x.finish);
::swap(end_of_storage, x.end_of_storage);
}
iterator insert(iterator position, const T& x) { //vector的插入函数
size_type n = position - begin();
if (finish != end_of_storage && position == end()) {
*finish = *position;
++finish;
} else
insert_aux(position, x); //vector的插入需要拷贝调整元素的位置,因而需要拷贝,效率低
return begin() + n;
}
iterator insert(iterator position) { return insert(position, T()); }
void insert (iterator position, const_iterator first,
const_iterator last);
void insert (iterator position, size_type n, const T& x);
void pop_back() { 弹出最后一个元素
--finish;
destroy(finish);
}
void erase(iterator position) { //删除vector的元素,删除最后一个值是常量时间,否则需要调整元素,重新拷贝,效率很低
if (position + 1 != end())
copy(position + 1, end(), position);
--finish;
destroy(finish);
}
void erase(iterator first, iterator last) {
vector<T /*, Alloc*/>::iterator i = copy(last, end(), first); //需要重新拷贝
destroy(i, finish); //删除需要删除的位置
finish = finish - (last - first);
}
void resize(size_type new_size, const T& x) { //调整vector的长度
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()); } //清除vector的所有元素,实现保证这个是线性时间的,O(n).
}
vector的常用接口就说到这里了,大家可以仔细体会。