stl::vector重要技术点
2021-08-10 本文已影响0人
gykimo
内存管理
下面这个代码是展示vector是添加扩容和删除
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> v;
int last_capacity = v.capacity();
for(unsigned long i =0;i<10000;i++){
int size = v.size();
int capacity = v.capacity();
v.push_back(i);
if(last_capacity!=v.capacity()){
cout<<"["<<i<<"] before:"<<size<<","<<capacity<<" after:"<<v.size()<<","<<v.capacity()<<endl;
last_capacity = v.capacity();
}
}
for(vector<int>::iterator iter = v.begin(); iter != v.end(); ){
iter = v.erase(iter);
}
cout<<"after erase :"<<v.size()<<","<<v.capacity()<<endl;
return 0;
}
Mac运行的日志如下:
[0] before:0,0 after:1,1
[1] before:1,1 after:2,2
[2] before:2,2 after:3,4
[4] before:4,4 after:5,8
[8] before:8,8 after:9,16
[16] before:16,16 after:17,32
[32] before:32,32 after:33,64
[64] before:64,64 after:65,128
[128] before:128,128 after:129,256
[256] before:256,256 after:257,512
[512] before:512,512 after:513,1024
[1024] before:1024,1024 after:1025,2048
[2048] before:2048,2048 after:2049,4096
[4096] before:4096,4096 after:4097,8192
[8192] before:8192,8192 after:8193,16384
after erase :0,16384
capacity代表实际分配的内存
- 可以看到初始vector内存是1,当内存不够扩容时,内存大小都是以2倍速度往上添加的
- 当删除元素时,内存大小不变
删除迭代器会失效
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> v1;
v1.resize(10000);
vector<int> v2;
v2.resize(10000);
vector<int> v3;
v3.resize(10000);
cout<<"v1 before:"<<v1.size()<<endl;
for(vector<int>::iterator iter = v1.begin(); iter != v1.end();){
iter = v1.erase(iter);
}
cout<<"v1 after erase:"<<v1.size()<<endl;
cout<<"v2 before:"<<v2.size()<<endl;
for(vector<int>::iterator iter = v2.begin(); iter != v2.end(); iter++){
v2.erase(iter);
}
cout<<"v2 after erase:"<<v2.size()<<endl;
cout<<"v3 before:"<<v3.size()<<endl;
vector<int>::iterator iter = v3.end();
iter--;
for(;iter != v3.begin(); iter--){
v3.erase(iter);
}
v3.erase(iter);
cout<<"v3 after erase:"<<v3.size()<<endl;
return 0;
}
可以看到erase后,v1和v3结果正确,但是v2结果不正确,原因是
- v2是先删除前面的,后删除后面的;但是如当删除第10个时,会将后面的元素都往前移动一位,因为vector在内存上是连续的。但是iter执行的是++,iter原来指向第10位,++后指向第11位,我们知道erase后,其实第11位已经移到了第10位,所以v2的操作方法实际是每隔一位删除一位,所以10000个元素,实际只删除了5000个;所以最终的size结果是5000;
1.1 说明vector的erase会将原来的迭代器失效,正确的写法就是v1的写法;
1.2 这个情况没有发生内存崩溃,是因为迭代器虽然失效了,但是错误的迭代器操作的内存还是vector实际分配好的内存,因为vector删除元素时内存不会变化;但如果某些逻辑迭代器++后指向不可用内存,可能会发生崩溃; - v3的写法也是正确的,因为是从后往前删除,这个时候vector的元素没有发生移动,所以iter不会失效;但是还是建议使用iter = v1.erase(iter);这种写法。