迭代器失效
我们之前说可能会不同编译器对迭代器的处理不同,使用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(); }