目录
vector结构
这里vector底层采用迭代器实现
template<class T>
typedef T* iterator;
typedef const T* const_iterator;
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
构造函数
默认构造
vector()
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
}
迭代器区间构造
//迭代器区间初始化
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push_back(*first);
first++;
}
}
拷贝构造
这里拷贝构造采用现代写法,用迭代器区间初始化一个tmp对象,然后交换。
需要注意的是这里的拷贝构造一定要使用初始化列表进行初始化!否则交换中会含有随机值,临时对象被销毁时会因为随机值造成程序崩溃!
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)
:_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;
}
}
容量大小相关函数
size
返回有效数据个数
size_t size()const
{
return _finish - _start;
}
capacity
返回容量大小
size_t capacity()const
{
return _endofstorage - _start;
}
empty
判空
bool empty()const
{
return _start == _finish;
}
reserve
扩容
这里扩容后如果使用memcpy拷贝数据,对于自定义类型而言将会造成浅拷贝问题!
void reserve(size_t n)
{
if (n > capacity())
{
T* tmp = new T[n];
size_t sz = size();
//memcpy(tmp, _start, sizeof(T) * sz);
//这里如果使用memcpy拷贝数据
//如果vector存的是自定义类型数据,
//可能造成浅拷贝问题,即一块空间析构两次!
if (_start)
{
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
resize
扩容+初始化
void resize(size_t n, const T& val = T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
if(n>capacity())
{
reserve(n);
}
while (_finish != _start + n)
{
*_finish = val;
_finish++;
}
}
}
operator[]
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
迭代器
反向迭代器实现
反向迭代器由正向迭代器组成,然后对其操作进行重载,这种结构对于其他容器而言都是通用的,
体现了泛型编程的优势。
template <class Iterator,class Ref,class Ptr>
class _reverse_iterator
{
public:
typedef _reverse_iterator<Iterator, Ref, Ptr> self;
_reverse_iterator(const Iterator& it)
:_it(it)
{
}
Ref operator*()
{
Iterator prev = _it;
return *--prev;
}
Ptr operator->()
{
return &(operator*());
}
bool operator==(const self& rit)
{
return _it == rit._it;
}
bool operator!=(const self& rit)
{
return _it != rit._it;
}
self& operator++()
{
_it--;
return *this;
}
self operator++(int)
{
self tmp(*this);
_it--;
return tmp;
}
self& operator--()
{
_it++;
return *this;
}
self operator--(int)
{
self tmp(*this);
_it++;
return tmp;
}
private:
Iterator _it;
};
迭代器实现
typedef T* iterator;
typedef const T* const_iterator;
typedef _reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef _reverse_iterator<const_iterator,const T&, const T*> const_reverse_iterator;
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rbegin()const
{
return const_reverse_iterator(end());
}
const_reverse_iterator rend()const
{
return const_reverse_iterator(begin());
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin()const
{
return _start;
}
const_iterator end()const
{
return _finish;
}
修改相关函数
push_back
尾插
void push_back(const T& val)
{
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
}
*_finish = val;
_finish++;
}
pop_back
尾删
void pop_back()
{
assert(_start != _finish);
_finish--;
}
insert
实现
iterator insert(iterator pos, const T& val)//返回新插入元素位置
{
//确保位置合法
assert(pos <= _finish);
assert(pos >= _start);
//保存位置,以防扩容后迭代器失效!
size_t len = pos - _start;
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;//扩容后要更改pos的位置!
}
iterator end = _finish;
while (end > pos)
{
(*end) = *(end - 1);
end--;
}
*pos = val;
_finish++;
return pos;
}
迭代器失效
insert中如果发生扩容,那么pos位置将会发生改变,要更新pos的位置,所以一开时计算一下pos的相对位置,如果发生扩容就更新!
插入后,如果继续使用当前迭代器而且没有接受返回值,将导致插入位置及后面元素迭代器失效!
当然,如果你插入后不使用迭代器,也就不会引发问题。
erase
实现
iterator erase(iterator pos)//返回被删除元素后一个元素的位置
{
assert(pos >= _start);
assert(pos < _finish);
iterator begin = pos + 1;
while (begin != end())
{
*(begin-1) = *begin;
begin++;
}
_finish--;
return pos;
}
迭代器失效
这里使用删除偶数场景:
场景1:1 2 3 4 崩溃
场景2:1 2 3 4 5 正常
场景3: 1 2 4 3 剩下1 4 3 没有删完
原因:erase后,后面的元素前移,导致错位。
而在某些环境下,对于迭代器失效的检查非常严格,如果erase后不接受返回值,又对迭代器进行操作,将会造成程序运行报错!
正确使用:
void erasenumber()//删除偶数
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
//v1.push_back(5);
vector<int>::iterator it = v1.begin();
while (it != v1.end())
{
//vs下对于迭代器失效的检查非常严格
//如果不接受返回值,那么就会引发失效问题,程序直接报错
if (*it % 2 == 0)
{
it = v1.erase(it);
}
else
{
it++;
}
}
for (auto x : v1)
{
cout << x << ' ';
}
}