作者最近在学习c++,学习侯捷的stl源码剖析这本书,但是我觉得里面的内容有些古老并且生涩。比如说alloc,对于一些基础知识不太牢固的同学不是很友好(我建议先细读第二章前4小节,第一级分配器之后的内容可等基础足够再回头弥补),虽然这本书本就不是面对像菜鸟的c++程序员。然一些基础思想,编程方法,可以试着学习学习。 本人在学习c++prime的同时,也曾自己实现过vector等contain。
这是一个实现vector的详细代码,我自己也实现了一份于不同于侯捷老师的vector,有需要的可以留言。。 这里我贴出stl源码剖析里面的代码,并且加了一些注释总体来说说得过去。 我改了一些细节, 可以对照着书上的看。
我标注了我实现的顺序,可以借鉴借鉴。。
#ifndef vector_hpp
#define vector_hpp
#include
#include
#include
template <typename T>
class vector
{
public:
/* 1 */
typedef T value_type; //声明T类型的别名
typedefvalue_type* pointer; //声明T*类型的别名指针
typedefvalue_type* iterator; //声明T*类型的别名迭代器 iterator就是迭代器,粘合剂。 : vector不需要定义迭代器
typedefvalue_type& reference; //左值
typedefsize_t size_type; //表示距离
typedefptrdiff_t difference_type; //表示指针间的距离
/* 3 */
//若干构造函数 为了代码的可读性省略了几个微不足道的考虑,如想了解可参考书
//default构造函数 拷贝构造函数 拷贝复制运算符必不可少
vector(): start(0),finish(0),end_of_storage(0) { }
vector(int n,const T& value)
{
fill_initialize(n, value);
}
/* 4 */
void fill_initialize(size_type n,const T& value)
{
start =allocate_and_fill(n, value);
finish =start + n;
end_of_storage =finish;
}
/* 5 */
//原本实现在private中。放至这里是便于程序更加易读性,故放在public。
iterator allocate_and_fill(size_type n, const T& value)
{
iterator result =data_allocator.allocate(n);
std::uninitialized_fill_n(result, n, value);
return result;
}
/* 6 */
iterator begin()
{
returnstart;
}
iterator end()
{
returnfinish;
}
size_type size()
{
returnsize_type(end() -begin());
}
constsize_type capacity()const
{
returnsize_type(end_of_storage -begin());
}
constbool empty()const
{
returnbegin() ==end();
}
//还有front和back函数返回相应的值
reference front() //注意是引用类型。下同
{
return *begin();
}
reference back()
{
return *(end() -1);
}
/* 7 */
//写完第六步的一些零零散散的‘配件’下面进入正题 push&pop
void push_back(const T& x)
{
if(finish !=end_of_storage)
{
// iterator p = finish;
data_allocator.construct(finish, x);
++finish;
// finish = p;
// std::cout << x << std::endl;
}
else
insert_aux(finish, x); //aux为辅助希腊语为增长-辅助的意思
}
void pop_back()
{
//--finish;
data_allocator.destroy(--finish);
}
iterator earse(iterator first,iterator last)
{
iterator i =std::copy(last,finish, first);
auto p = i;
data_allocator.destroy(++p);
finish =finish - (last - first);
returnfinish;
}
iterator earse(iterator pos)
{
if(pos +1 !=end())
std::copy(pos +1,finish, pos);
--finish;
data_allocator.destroy(finish);
return pos;
}
void clear()
{
earse(begin(),end());
}
/*
*/
void insert(iterator pos,size_type n,const T& x)
{
if(n !=0) //虽然n != 0在这里很微不足道,很渺小。但是依旧要重视
{
if(size_type(finish - end_of_storage) >= n)
{
T x_copy = x;
constsize_type elems_after =finish - pos;
iterator old_finish =finish;
if(elems_after >= n)
{
std::uninitialized_copy(finish - n, finish,finish);
finish += n;
std::fill(pos, pos + n, x_copy);
}
else
{
std::uninitialized_fill_n(finish, n - elems_after, x_copy);
finish += n - elems_after;
std::uninitialized_copy(pos, old_finish,finish);
finish += elems_after;
std::fill(pos, old_finish, x_copy);
}
}
else
{
constsize_type old_siez =size();
constsize_type len = old_siez +std::max(old_siez, n);
iterator new_start =data_allocator.allocate(len);
iterator new_finish =finish;
new_finish = std::uninitialized_copy(start, pos, new_start);
new_finish = std::uninitialized_fill_n(new_finish, n, x);
new_finish = std::uninitialized_copy(pos,finish, new_finish);
start = new_start;
finish = new_finish;
end_of_storage = new_start + len;
}
}
}
private:
/* 2 */
iterator start; //指向第一个的迭代器指针
iterator finish; //指向第一个空闲没有实参的迭代器指针
iterator end_of_storage; //指向尾后迭代器的迭代器指针
std::allocator<int> data_allocator;
/* 8 */
//接下来考虑动态数组内存不够的情况
void insert_aux(iterator position,const T& x) //position :安置;把…放在适当位置
{
//
const size_type old_size =size(); //旧的动态数组的大小
constsize_type len = old_size !=0 ? 2 * old_size :1; //如果old_size不为0 * 2 否则大小为1;
iterator new_start =data_allocator.allocate(len); //新建一块动态数组是原来的两倍
iterator new_finish = new_start; //指向同一个地址
new_finish = std::uninitialized_copy(begin(), position, new_start); //将原先的vector内的对象拷贝到新的vector里
data_allocator.construct(new_finish, x); //为新的元素设置为x
++new_finish;
//new_finish = uninitialized_copy(position, finish, new_finish); //这一行跟push_back没有太大关系用途是在insert这个函数因为insert_aux的第一个参数不一定是end()
start = new_start;
finish = new_finish;
end_of_storage = new_start + len;
}
};