vector图示详解:
图来自《stl源码分析》
namespace yhy
{
template<class T>
class vector
{
public:
typedef T* iterator;//定义了一个简单的迭代器,迭代器在stl中起到指针的作用,但是有时候纯指针的迭代器在一些数据结构中如list中无法起到所有作用,所以有时候是指针,有时候是自定义类型。
typedef const T* const_iterator; //const 迭代器保证在遍历vector时不会意外地修改元素的值
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator cbegin()const
{
return _start;
}//cbegin()函数返回一个const_iterator类型的迭代器,指向vector的第一个元素
const_iterator cend()const//同上
{
return _finish;
}//
vector()//无参构造
:_start(nullptr), _finish(nullptr), _endOfStorage(nullptr){}
vector(int n, const T& value = T())
{
_start = new T[n];
_finish = _endOfStorage = _start + n;
for (int i = 0; i < n; i++)
{
push_back(value);
}
}
~vector()
{
delete[] _start;
_start = _finish = _endOfStorage = nullptr;
}
template<class InputIterator>
vector(InputIterator first, InputIterator last)
:_start(nullptr), _finish(nullptr), _endOfStorage(nullptr)//注意在初始化列表的时候,对象就已经被实例化了,因此可以进行后面代码的操作
{
_start = first; _finish = _endOfStorage = last;
iterator i = first;
while (i < last)
{
push_back(*i);
i++;
}
}
vector(const vector<T>& v)
{
vector<T> tmp(v._start, v.cend);//在这里我们要先实例化一个tmp是由于进行深拷贝,不实例化会浅拷贝,如果浅拷贝,导致一个空间被重复释放造成程序崩溃
swap(tmp);
}
vector<T>& operator= (vector<T> v)//与上面同理,为何要将两个对象进行交换?而不直接赋值?因为直接赋值会使得两个对象中的_start,_finish指针指向同一个空间,也就是只进行了浅拷贝
{
swap(v);
return *this;
}
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _endOfStorage - _start;
}
void reserve(size_t n)
{
if (n > capacity())//如果n大于目前容量,则扩容,然后将原数据迁移到现空间内
{
size_t size = _finish - _start;
T* tmp = new T[n];
for (size_t i = 0; i < size; i++)
{
tmp[i] = _start[i];//想象一下如果vector里成员也是一个vector对象会怎么样?必须要进行深拷贝1,而这里的=符号将会使用我们重载的那个=
}
_start = tmp;
_finish = _start + size;
}
_endOfStorage = _start + n;
}
void resize(size_t n, const T& value = T())
{
if (size() < n )
{
if (n > capacity())
{
resize(n);
}
while (_finish < _start + n)
{
*_finish = value;
_finish++;
}
}
else
{
_finish = _start + n;
}
}
T& operator[](size_t pos)
{
return *(_start + pos);
}
const T& operator[](size_t pos) const
{
return *(_start + pos);
}
void push_back(const T& x)
{
if (_finish ==_endOfStorage)
{
size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newcapacity);
}
*_finish = x;
_finish++;
}
void pop_back()
{
assert(size() > 0);
_finish--;
}
void swap(vector<T>& v)
{
iterator tmp = nullptr;
tmp = _start;
}
iterator insert(iterator pos, const T& x)//由于该成员函数由于扩容问题,可能会导致迭代器失效因此不能直接用传参的pos,而应该用它计算pos到——start的距离,再传入一个新pos
{
assert(pos >= _start);
assert(pos < _finish);
size_t len = pos - _start;
if (_finish == _endOfStorage)
{
size_t newcapacity = capacity() == 0 ? 1 : 2 * capacity();
reserve(newcapacity);
}
iterator newpos = _start + len;
iterator i = _finish;
for (i; i > newpos; i--)
{
*i = *i + 1;
}
*newpos = x;
++_finish;
}
iterator erase(iterator pos)//由于erase会发生迭代器失效,由于erase在删除数据时会发生移动,因此如果刚好删除的是最后一个元素时,一但后面的数据移动,判断就会失效,那么将会无限循环,因此如果想使用这种函数,那么一定要接收erase的返回值再进入循环进行判断
{
return nullptr;
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endOfStorage v._start);
}
private:
iterator _start; // 指向数据的开始
iterator _finish; // 指向有效数据的尾
iterator _endOfStorage; // 指向存储容量的尾
};
}