vector的成员变量
- _start:指向元素开始的位置
- _finish:指向最后一个元素的下一个位置
- _endofstorage:指向从堆区开辟的空间的末尾的下一位置
template<class T>
class vector
{
public:
//迭代器
typedef T* iterator;
typedef const T* const_iterator;
//反向迭代器迭代器
typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
typedef reverse_iterator<iterator, T&, T*> reverse_iterator;
//、、、、、、
//各种成员函数
//、、、、、、
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
};
构造函数
1、无参构造
vector()
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{}
2、采用迭代器的构造方法
template<class InputerIterator>//新建一个模板参数是为了可以传多种迭代器,而不是只能传vector的迭代器
vector(InputerIterator first, InputerIterator last)//vector有一种构造方法是vector v(v1.begin(),v1.end())
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
while (first != last)
{
push_back(*first);
++first;
}
}
3、拷贝构造
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
vector(const vector<T>& v)//拷贝构造必需传引用,如果不传引用,就是传值,传值又是一次拷贝构造,进而死循环,所以不能像operator=那样写。
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
vector<T> tmp(v.begin(), v.end());
swap(tmp);
}
赋值运算符重载
vector<T>& operator=(vector<T> v)
{
swap(v);
return *this;
}
析构函数
~vector()
{
if (_start)
{
delete[] _start;//销毁所开辟的所有空间
_start = _finish = _endofstorage = nullptr;
}
}
reverse()扩容
size_t size() const
{
return _finish - _start;//指针-指针,因为同类型得到的是这段空间的元素的个数。
}
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)//_start不为空,说明原来有数据,要拷贝
{
//memcpy是浅拷贝,当T是string时,字符串是存在堆中的,string只存了指向这个字符串的指针、size、capacity。
//因此使用memcpy也只是把指针的地址重新赋值给了tmp,当delete[] _start;就已经销毁了字符串的空间。
//然后tmp又赋值给了_start,程序结束,调用析构函数,又要再次销毁字符串的空间,同一块空间被释放了2次,程序错误
//因此不能使用memcpy
//memcpy(tmp, _start, sizeof(T) * size());//大部分情况是对的,但是涉及深拷贝问题会有错误
for (size_t i = 0; i < sz; i++)
{
//相当于string =string 调用了string类中的operator=,operator是深拷贝。
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
// _finish = _start + size();这句代码有误,因为_start的位置改了,所计算的size也是错的,应该提前保存原来数组的大小,即sz
_finish = _start + sz;
_endofstorage = _start + n;
}
}
push_back
当_finish == _endofstorage说明空间不够需要扩容。
void push_back(const T& x)
{
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : (capacity() * 2));
}
*_finish = x;
++_finish;
}
resize()
void resize(size_t n, const T& val = T())//const &会延长匿名对象的生命周期,延长到整个作用域,而不是仅是这一行代码
{
if (n < size())//如果定义的空间比原来还要小,即让finish指向_start+n的位置,而不用销毁空间
{
_finish = _start+n;
}
else
{
if (n > capacity())//定义的n大于容量了,扩容
{
reserve(n);
}
while (_finish != _start + n)//赋值
{
*_finish = val;
_finish++;
}
}
}
insert
iterator insert(iterator pos, const T& x)//传迭代器是规定,看文档;返回值要返回新插入元素位置的迭代器,也是为了处理迭代器失效问题
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
// 扩容会导致pos失效,扩容需要更新一下pos,因为扩容可能是异地扩容
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : (capacity() * 2));
pos = _start + len;
}
iterator end = _finish - 1;
//这个while循环是将数据往后挪一个位置
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
_finish++;
return pos;
}
erase
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);//这里不能用=,因为可能要删除最后一个元素
iterator begin = pos + 1;//让pos后一个元素 覆盖 pos位置上的元素
while (begin < _finish)
{
*(begin - 1) = *begin;
begin++;
}
--_finish;
return pos;
}
剩余的简单成员函数
void pop_back()//尾删
{
assert(_finish > _start);
--_finish;
}
const T& operator[](size_t i)const
{
assert(i < size());
return _start[i];
}
T& operator[](size_t i)
{
assert(i < size());
return _start[i];
}
size_t capacity() const//返回容量大小
{
return _endofstorage- _start;
}
正向迭代器
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
反向迭代器
方向迭代器的rbegin在正向迭代的end上,反向迭代器rend在正向迭代器的begin上。
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
我们为反向迭代器新建了一个类
namespace Lgc
{
//反向迭代器的end就是正向迭代器的begin,反向迭代器的begin就是正向迭代的end,这样写是为了复用正向迭代器
//因为用的是模板,这个反向迭代器同时也可以给其他容器使用。(如vector)
template<class Iterator,class Ref,class Ptr>
class reverse_iterator
{
typedef reverse_iterator<Iterator, Ref, Ptr> self;
public:
reverse_iterator(Iterator it)
:_it(it)
{
}
Ref operator*()
{
Iterator prev = _it;//prev不能是self类型,因为如果是self则prev是个反向迭代器,--还是一个反向迭代器,在*就是调用自己的operator*,然后一直调用自己的operator*,直到栈溢出(3.15 2:41:45) 我们的本意是去调用正向迭代器的operator*
return *(--prev);//因为rbegin在正向迭代器的end上,而end的位置在_finish的位置上,要获取元素,所以要--
}
Ptr operator->()
{
return &(operator*());
}
self& operator++()
{
--_it;
return *this;
}
self operator++(int)
{
self tmp(*this);
--_it;
return tmp;
}
self& operator--()
{
++_it;//因为是反向迭代的原因,--在逻辑是就是++
return *this;
}
bool operator!= (const self& rit) const
{
return _it != rit._it;//这个不等于是调用了正向迭代器的运算符重载!=
}
private:
Iterator _it;
};
}