迭代器失效
我们之前说可能会不同编译器对迭代器的处理不同,使用vs vector库里的会强制检查,如果使用g++里面的,对于earse不会检查,由于我们vector的底层实现是看的g++的源码,所以我们不使用vs vector库,默认我们是在g++下编译,那这里g++针对迭代器失效不会报错吗???实际上会的,但是展示出来的错误,不会让你联想到迭代器失效,其实本质就是迭代器失效
举个例子,要在vector v1中删除偶数位(代码是上篇vector里面的,加一个测试函数)
void test7()//测试函数
{
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())
{
if (*it % 2 == 0)
v1.erase(it);
++it;
}
for (auto e : v1)//范围for
{
cout << e << " ";
}
}
当你编译这段代码是时,你会发现没问题。
如果你将5去掉之后呢??
我们看到报错是因为pos<_finish???我们可以来模拟一下
那如果修改it<_finish不就行了??
结果是这样吗??
将1修改成10,发现结果不对了
如果是5个的话,最后一个是偶数也不对
总结:这些上述错误都是迭代器失效引起的,而结果可能不会让你联想到迭代器失效
其实我们可以通过earse返回下一个位置,就可以解决这里的问题辣
为什么string里面有迭代器失效吗??vector一般用的是原生迭代器,而string和list是别的方式,很少会出现迭代器失效
vector模拟的完善
~vector()//析构函数
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
vector(size_t n, const T& val = T())//用n个val来初始化
{
reserve(n);
for (int i = 0; i < n; i++)
{
push_back(val);
}
}
void test8()
{
vector<int>v1(10, 5);
for (auto e : v1)//范围for
{
cout << e << " ";
}
}
在vs2013中左边是不行的,没有对三个值初始化
vs2019优化会处理这里的未初始化
使用迭代器用其他区间来初始化,这里也可以用string,没有用iterator来局限只能用vector
template <class InputIterator>
vector(InputIterator first, InputIterator end)
{
while (first != end)
{
push_back(*first);
first++;
}
}
也可以用string区间来初始化
void test9()
{
vector<int>v1(10u, 5);
string str = "hello";
vector<int>v2(str.begin(), str.end());
for (auto e : v1)//范围for
{
cout << e << " ";
}
cout << endl;
for (auto e : v2)//范围for
{
cout << e << " ";
}
}
用数组来初始化(用的上面第二种)
void test10()
{
int arr[10] = { 25,6,3,78,45,12,36,42,1,15 };
vector<int>v2(arr,arr+10);
for (auto e : v2)//范围for
{
cout << e << " ";
}
}
使用sort排序
#include<algorithm>
void test10()
{
int arr[10] = { 25,6,3,78,45,12,36,42,1,15 };
vector<int>v2(arr,arr+10);
sort(v2.begin(), v2.end());
sort(arr,arr+10);
for (auto e : v2)//范围for
{
cout << e << " ";
}
cout << endl;
for (auto e : arr)//范围for
{
cout << e << " ";
}
}
拷贝构造
vector(const vector<T>& v)
{
_start = new T[v.capacity()];
memcpy(_start, v._start, sizeof(T) * v.size());
_finish = _start + v.size();
_end_of_storage = _start + v.capacity();
}
vector的深拷贝和浅拷贝
内置类型的拷贝(浅拷贝)
vector<int>v2(10u,5);
vector<int>v3(v2);
for (auto e : v2)//范围for
{
cout << e << " ";
}
cout << endl;
for (auto e : v3)//范围for
{
cout << e << " ";
}
cout << endl;
}
自定义类型的拷贝
void test11()
{
vector<std::string>v2(3,"11111111111111111111111");
vector<std::string>v3(v2);
for (auto e : v2)//范围for
{
cout << e << " ";
}
cout << endl;
for (auto e : v3)//范围for
{
cout << e << " ";
}
cout << endl;
}
这里浅拷贝是按照字节一个一个拷贝,就会出现指向同一空间,当v3析构后,指向字符串那里的值已被释放,再次释放就会出错
所以我们必须使用深拷贝,修改拷贝构造
vector(const vector<T> & v)
{
_start = new T[v.capacity()];
/* memcpy(_start, v._start, sizeof(T) * v.size());*/
for (int i = 0; i < v.size(); i++)
{
_start[i] = v._start[i];
}
_finish = _start + v.size();
_end_of_storage = _start + v.capacity();
}