美文网首页
stl::vector重要技术点

stl::vector重要技术点

作者: gykimo | 来源:发表于2021-08-10 10:24 被阅读0次

    内存管理

    下面这个代码是展示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);这种写法。

    相关文章

      网友评论

          本文标题:stl::vector重要技术点

          本文链接:https://www.haomeiwen.com/subject/emlmvltx.html