vector的基本使用
vector是C++中非常常见的容器,可以存储任意类型的数据,而vector也可以成为动态数组,他是支持扩容和缩容的,下面来介绍一些vector的接口:
1,创建
头文件:#include
vector<数据类型> 自定义名称
也可以使用另一个vector来初始化
也可以在初始化时,指定大小和参数
如果只指定大小,里面的值默认是0
也可以用迭代器和指针来初始化
2,插入
push_back:尾插数据
emplace_back:尾插数据
insert:指定位置前一个位置插入数据(参数为迭代器和要插入的值)
3,删除
pop_back:尾删
erase:删除指定数据(参数是迭代器)
删除指定单个数据
删除指定区间数据
clear:清空所有数据
4,扩容和获取容器大小
size:获取容器有效运输个数
capactiy:获取容器总大小
reserve:将容器总空间扩容
resize:将情况有效数据的个数进行扩容
也可以在扩容的同时,初始化
5,缩容
有效数据空间缩容(resize)
有效数据空间缩容,并不会影响总空间大小
6,其他接口
size:返回有效数据个数
capacity:返回总空间大小
max_size:返回容器的大小
bagin:返回第一个元素的迭代器
end:返回最后一个元素的迭代器的下一个位置
rbegin:返回最后一个元素的的迭代器
rend:返回第一个元素的迭代器的上一个位置
cbegin:返回第一个元素
cend:返回最后一个元素
empty:判断容器是否为空
at:查找某个元素是否在容器内
back:返回最后一个元素
vector的模拟实现
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace ys
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
vector()
:_start(nullptr)
,_finish(nullptr)
,_end_of_storage(nullptr)
{
}
vector(size_t n,const T& i = T())
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
reserve(n);
for (int x = 0; x < n; x++)
{
push_back(i);
}
}
template<class InputIterator>
vector(InputIterator begin, InputIterator end)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
while (begin != end)
{
push_back(*begin);
begin++;
}
}
vector(vector<T>& v)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
reserve(v.capacity());
int size = v.size();
for (int i = 0; i < size; i++)
{
push_back(v[i]);
}
}
void swap(vector<T>& v)
{
std::swap(_start,v._start);
std::swap(_finish,v._finish);
std::swap(_end_of_storage,v._end_of_storage);
}
vector<int>& operator = (vector<T> v)
{
swap(v);
}
vector(const vector<T>& v)
{
//_start = new T[v.capacity()];
memcpy(_start, v._start, sizeof(T)*v.size());
//for (size_t i = 0; i < v.size(); ++i)
//{
// _start[i] = v._start[i];
//
//}
//_finish = _start + v.size();
//_end_of_storage = _start + v.capacity();
//现代写法
//创建一个临时对象,然后使用swap交换
vector<T> x(v.begin,v.end);
swap(x);
}
//返回有效数据个数
size_t size()
{
return _finish - _start;
}
//扩容总空间
void reserve(size_t n)
{
if (n > capacity())
{
//记录finish位置
int i = _finish - _start;
//拷贝数据
T* tmp = new T[n];
if (_start)
{
memcpy(tmp,_start,sizeof(T) * size());
//释放旧空间
delete[] _start;
}
//更新地址
_start = tmp;
_finish = _start + i;
_end_of_storage = _start + n;
}
}
//扩容有效空间并初始化
//带参的函数重载
void resize(size_t n,T pos = T())
{
//判断扩容
if (n > capacity())
{
//扩容
reserve(n);
while (_finish != _start + n)
{
*_finish = pos;
++_finish;
}
}
else if (n < size())
{
//缩容,有效数据缩容,而不是缩容整个空间大小
_finish = _start + n;
}
//if (n < size())
//{
// // 删除数据
// _finish = _start + n;
//}
//else
//{
// if (n > capacity())
// reserve(n);
// while (_finish != _start + n)
// {
// *_finish = pos;
// ++_finish;
// }
//}
}
//尾插
void push_back(T x)
{
//判断容量
if (_finish == _end_of_storage)
{
//扩容
reserve(_finish - _start == 0 ? 4 : capacity() * 2);
}
*_finish = x;
_finish++;
}
//尾删
void pop_back()
{
assert(!empty());
_finish--;
}
//指定位置插入
iterator insert(iterator pos, const T& val)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _end_of_storage)
{
//扩容前记录迭代器的位置,防止迭代器失效
size_t i = pos - _start;
//扩容
reserve(capacity() == 0 ? 4 : capacity() * 2);
//更新pos的位置
pos = _start + i;
}
//将数据向后挪动
T* end = _finish + 1;
while (end >= pos)
{
*end = *(end - 1);
end--;
}
//插入数据
*pos = val;
//有效数据个数++
_finish++;
//返回当前位置的迭代器
return pos;
}
//指定位置删除
void erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
T* end = pos;
while (end < _finish)
{
*end = *(end + 1);
end++;
}
--_finish;
/*assert(pos >= _start);
assert(pos < _finish);
iterator start = pos + 1;
while (start != _finish)
{
*(start - 1) = *start;
++start;
}
--_finish;*/
}
//判空
bool empty()
{
return _finish == _start;
}
//返回总空间大小
size_t capacity()
{
return _end_of_storage - _start;
}
//迭代器
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
iterator const_begin() const
{
return _start;
}
iterator const_end() const
{
return _finish;
}
T& operator[](size_t i)
{
assert(!empty());
return _start[i];
}
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
}
vector迭代器问题
1,迭代器失效问题:
此时i是否还能解引用操作呢?
不能,如果强行去解引用,会报错
但是可以erase函数会返回删除后的下一个元素的迭代器
2,反向迭代器
在使用正向迭代器,begin,end的时候
如果想要往后走,可以使用++操作,往前走可以使用–操作
在++和–操作的时候,逻辑结构是线性的
使用反向迭代器,rbeign返回的是最后一个元素的下一个位置,rend返回的是第一个元素的位置,如果要通过rbegin或者end遍历容器,比如说用rbegin从后向前遍历,应该让rbegin每次 – ,可设计师却不这么想,如果想要用rbegin向后走,要用++,也就是说rbegin的++和–操作是相反的:
同理,如果用rend去遍历,要用–: