目录
1.vector对象的构造方式:
2.vector对象的三种遍历方式:
3.和容量相关联的使用:
1.有效元素的获取和空间大小的获取。
2.resize:将顺序表有效元素个数增加。
resize的使用:
我们知道它在增大有效元素个数时如果空间不够会扩容我们测试一下他是如何扩容的
运行结果
可以得出结论,在扩容时是按照1.5倍扩容的(在vs平台下,在g++下是按照2倍),但是当减少有效字符个数时并不会减少容量。
3.reserve:扩容
使用:只是单纯的将容量增大了,并没有填充其他内容
我们来测试一下它的扩容规律(在vs平台下):
运行结构:
我们可以得出结论就是在传入新的容量大于原来容量时,会按照传入容量的大小来扩容(我猜测是因为实现者考虑到如果是有些使用者用比较大的自定义类型来填充顺序表时如果开辟的空间过多会造成浪费所以按需开辟)。
4.获取元素:
1.front和back
2.'[]'运算符重载
5.操作元素:
1.push_back和pop_back
2.insert:
运行结果:
3.clear()清空元素
4.erase删除某个位置的元素或者某个区间元素
运行结果:
5.交换两个对象
运行结果:
6.vector迭代器失效:
1.什么是迭代器?
迭代器就是类似于指针的东西,对它操作就和对指针一样的操作方式。
2.为什么会迭代器失效?
我们先来看迭代器失效的一个场景
我们可以看到在一开始我们将迭代器创建出来,然后插入元素,当容器扩容后对迭代器进行解引用访问就报错了,这是因为,在进行扩容时,底层直接就将原来旧的空间释放掉,然后将内容拷贝到新开辟的空间中,将原来的指针指向新的空间,而这样迭代器的那片空间就被释放掉了,所以扩容之后再对迭代器进行操作,就有可能会导致迭代器失效问题。
3.那么那些操作会导致迭代器失效呢?
首先导致迭代器失效的原因就是容器扩容到导致迭代器指向的旧空间的释放然后导致迭代器失效。所以一切有可能导致扩容的操作都有可能导致迭代器失效如:
push_back()
clear()
按理说只有当容器扩容时地址改变才会产生迭代器失效的错误,这里是为什么呢?我们再去g++编译器试一下看一下会不会报错
运行结果我们发现并没有报错正常运行,所以使用clear清空元素,然后出现迭代器失效的情况应该是在vs平台下检测严格才会报错。
insert()
erase()
同理我们来测试一下删除首元素在g++平台下会不会导致迭代器失效
运行结果:我们发现也并没有报错,那我们就可以得出一个结论在vs平台下只要首元素被删除那么就会产生迭代器失效的错误。
这里要注意删除其他位置元素是不会导致迭代器失效的
reverse()
resize()
operator=
assign()
swap()
4.怎样避免迭代器失效:
1.在使用erase时由于erase删除当前迭代器的位置,他就会返回下一个迭代器的位置,所以我们只需要每次将迭代器位置删除后更新即可。
7.vector的模拟实现
#include<iostream>
#include<assert.h>
#include<vector>
using namespace std;
namespace wbx
{
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 &val = T())//构造n个T类型的val值
:_start(nullptr)//指针要初始化这是一个良好的编程习惯
,_finish(nullptr)
,end_of_storage(nullptr)
{
_start = new T[n*sizeof(T)];
_finish = _start+n;
end_of_storage = _finish;
for (size_t i = 0; i < n; i++)
{
_start[i] = val;
}
}
vector(int n,const T &val = T())//构造n个T类型的val值,这里的val必须要用const修饰不然当传入参数时是编译通过不了的
:_start(nullptr)//指针要初始化这是一个良好的编程习惯
, _finish(nullptr)
, end_of_storage(nullptr)
{
_start = new T[n*sizeof(T)];
_finish = _start + n;
end_of_storage = _finish;
for (int i = 0; i < n; i++)
{
_start[i] = val;
}
}
vector(const vector<T> &v)//拷贝构造
:_start(nullptr),
_finish(nullptr),
end_of_storage(nullptr)
{
//vector temp(v.begin(), v.end());//这里不可以调用普通类型的返回迭代器的指针,
vector<T> temp(v.cbegin(), v.cend());//因为const对象只能调用const类型的成员函数
this->swap(temp);
}
template<class Iterator>//这里要再定义一个迭代器类的模板,因为这里假设我们vector中存放的不同类型对象
//所返回的迭代器类型也是不同的,所以我们这里重新设置一个模板类对于多种不同
//类型具有普遍的适用性
vector(Iterator first, Iterator last)
{
size_t n = last - first; //这里获取frist和last之间的距离应当写一个distance函数来
//获取他们之间的距离,这里这样写是因为简单模拟实现
_start = new T[n];
_finish = _start;
end_of_storage = _start + n;
while (first != last)
{
*_finish = *first;
_finish++;
first++;
}
}
~vector()
{
if (_start)
{
delete[] _start;
_start = nullptr;
_finish = nullptr;
end_of_storage = nullptr;
}
}
运算符重载:
vector <T>operator=(vector<T> v)
{
this->swap(v);
return *this;
}
T& operator[](size_t index)
{
if (index < 0 || index >= size())
{
assert(false);
}
return *(_start + index) ;
}
///容量相关
size_t size()
{
int a = 0;
return a=_finish - _start;
}
size_t capacity()
{
return end_of_storage - _start;
}
bool empty()
{
if (_start == _finish)
{
return true;
}
return false;
}
void resize(size_t n, T val = T())
{
size_t oldsize = size();
if (n >capacity())
{
reserve(n - capacity());
}
for (int i = oldsize; i < n; i++)
{
_start[i] = val;
}
_finish = _start + n;//如果新的size小于老的size这里直接访问不到了
}
void reserve(size_t n)
{
T *temp = new T[n];
for (int i = 0; i < size(); i++)
{
temp[i] = _start[i];//这里必须要用=来进行拷贝如果用其他如memcpy的话就会发生浅拷贝的情况
}
size_t oldsize = size();
if (_start)
{
delete[] _start;
}
_start = temp;
_finish = _start + oldsize;
end_of_storage = _start + n;
}
迭代器
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator cbegin()const
{
return _start;
}
const_iterator cend()const
{
return _finish;
}
/插入函数
void push_back(T val)
{
if (_finish == end_of_storage)
{
reserve(2 * capacity());
}
*_finish = val;
_finish++;
}
void pop_back()
{
if (empty())
{
assert(false);
}
_finish--;
}
iterator insert(iterator pos,T val)
{
if (empty()||pos==_finish)
{
push_back(val);
return pos;
}
if (_finish == end_of_storage)
{
reserve(capacity() + 1);
}
iterator temp = _finish-1;
while (temp >= pos)
{
*(temp + 1) = *temp;
temp--;
}
*pos = val;
_finish++;
return pos;
}
iterator erase(iterator pos)
{
if (pos < _start || pos >= _finish)
{
assert(false);
}
iterator ret = pos;
while (pos != _finish - 1)
{
*pos = *(pos + 1);
pos++;
}
_finish--;
return ret + 1;
}
T & front()
{
return *(_start);
}
T &back()
{
return *(_finish-1);
}
交换函数
void swap(vector <T> &v)
{
std::swap(v._start, _start);
std:: swap(v._finish, _finish);
std::swap(v.end_of_storage, end_of_storage);
}
private:
iterator _start;
iterator _finish;
iterator end_of_storage;
};
}
using namespace std;
wbx::vector<int> static v4(5, 4);
void test1()
{
wbx::vector<int> v1(5, 1);
wbx::vector<int> v2(5, 2);
wbx::vector<int> v3(v2);
v1.reserve(10);
v1[3] = 0;
v2 = v1;
v2[1] = 0;
//static wbx::vector<int> v3(5, 3);
v1.resize(10, 9);
v1.pop_back();
v1.push_back(11);
v1.push_back(11);
v1.insert(v1.begin() + 1, 100);
v1.erase(v1.begin() + 3);
v1.erase(v1.begin() + 3);
v1.back()++;
}
int main()
{
//test1();
return 0;
}