一.vector的基本使用
基本函数的使用
点上面
只需要在自己的编译器下适当练习掌握就可
二.vector的模拟实现
#include<iostream>
#include<cstdio>
using namespace std;
namespace zkx
{
template<class T>
class vector
{
public:
// Vector的迭代器是一个原生指针
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end() {
return _finish;
}
const_iterator cbegin()const
{
return _start;
}
const_iterator cend() const
{
return _finish;
}
// construct and destroy
vector()
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{}
vector(int n, const T& value = T())
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
reserve(n);
while (n--)
{
push_back(value);
}
}
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
reserve(last - first);
while (first != last)
{
push_back(*first);
++first;
}
}
//拷贝构造
vector(const vector<T>& v)
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
reserve(v.size());
iterator it = begin();
const_iterator vit = v.begin();
while (vit != v.cend())
{
*it = *vit;
}
_finish = _start + v.size();
_endofstorage = _start + v.capacity();
}
vector<T>& operator= (vector<T> v)
{
swap(v);
return *this;
}
~vector()
{
delete[] _start;
_start = _finish = _endofstorage = nullptr;
}
// capacity
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _endofstorage - _start;
}
void reserve(size_t n)
{
if (n > capacity()) {
size_t sz = size();
T* tmp = new T[n];
if (_start)
{
for (int i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
}
delete[] _start;
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
void resize(size_t n, const T& value = T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
if (n > capacity())
{
reserve(n);
}
while (_finish != _start + n)
{
*_finish = value;
++_finish;
}
}
}
///access///
T& operator[](size_t pos)
{
return _start[pos];
}
const T& operator[](size_t pos)const
{
return _start[pos];
}
///modify/
void push_back(const T& x)
{
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : 2 * capacity());
}
*_finish = x;
_finish++;
}
void pop_back()
{
assert(_finish > _start);
_finish--;
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
size_t sz = size();
reserve(capacity() == 0 ? 4 : 2 * capacity());
pos = sz + _start;
}
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
end--;
}
*pos = x;
_finish++;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos <= _finish);
iterator begin = pos + 1;
while (begin < _finish)
{
*(begin - 1) = *begin;
begin++;
}
--_finish;
return pos;
}
private:
iterator _start; // 指向数据块的开始
iterator _finish; // 指向有效数据的尾
iterator _endofstorage; // 指向存储容量的尾
};
void test()
{
vector<int> vv;
vv.push_back(1);
vv.push_back(2);
vv.push_back(3);
vv.push_back(4);
vector<int>::iterator it = vv.begin();
while (it != vv.end())
{
cout << *it << endl;
it++;
}
vector<int> vv1(5,2);
}
}
三 .vector 迭代器失效原因
迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,如果继续使用已经失效的迭代器,程序可能会崩溃
细分有三种:
1 . 当容器调用erase时,当前位置到容器末尾元素的所有的迭代器全部失效
2 . 当容器调用insert时,当前位置到容器末尾元素的所有的迭代器全部失效;
3 . 当容器调用insert时,如果引起容器内存扩容,原来容器的所有的迭代器就全部失效
对于vector,可能会导致迭代器失效的操作有:
1 .会引起其底层空间的改变,可能会失效(resize,reserve,insert…)
出错原因:
以上操作,都有可能导致vector扩容,也就是说vector底层原理旧空间被释放掉,在打印时,it使用的还是旧的空间,在对it迭代器操作时候,实际操作的是已经被释放掉的空间,从而引起代码崩溃
解决方式:在以上操作完成之后,如果想要通过迭代器操作vector中的元素,只需给it重新赋值就行
2.指定位置元素的删除操作 - erase
有可能是vector在删除的时候进行了缩容,意义变了,指向的不是原来的空间的;还有可能是变成野指针
例子:
我们发现在删4的时候发生了异常
删最后一个元素的时候,将_finish指向的end,是没有元素的,给给pos,迭代器会失效
用一个it来接收是没有问题的