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代表实际分配的内存

  1. 可以看到初始vector内存是1,当内存不够扩容时,内存大小都是以2倍速度往上添加的
  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结果不正确,原因是

  1. v2是先删除前面的,后删除后面的;但是如当删除第10个时,会将后面的元素都往前移动一位,因为vector在内存上是连续的。但是iter执行的是++,iter原来指向第10位,++后指向第11位,我们知道erase后,其实第11位已经移到了第10位,所以v2的操作方法实际是每隔一位删除一位,所以10000个元素,实际只删除了5000个;所以最终的size结果是5000;
    1.1 说明vector的erase会将原来的迭代器失效,正确的写法就是v1的写法;
    1.2 这个情况没有发生内存崩溃,是因为迭代器虽然失效了,但是错误的迭代器操作的内存还是vector实际分配好的内存,因为vector删除元素时内存不会变化;但如果某些逻辑迭代器++后指向不可用内存,可能会发生崩溃;
  2. v3的写法也是正确的,因为是从后往前删除,这个时候vector的元素没有发生移动,所以iter不会失效;但是还是建议使用iter = v1.erase(iter);这种写法。
上一篇下一篇

猜你喜欢

热点阅读