std::vector刪除元素迭代器以及內存的變化

 std::vector是順序容器,當用erase成員函數刪除一個迭代器指向的元素時,會自動移動(不是std::move)後面的元素到前面來,而迭代器的指向不變(如果是std::map、std::list這類關聯型容器,迭代器會失效),並且不會回收內存(也就是capacity不會變)。當用swap成員函數跟自身的拷貝交換時,才能釋放多餘內存。

代碼如下,自定義一個foo類以監視構造、賦值、複製、移動、析構等情況。

#include <iostream>
#include <vector>
class foo{
    int a;
public:
    foo(int x=0):a(x){std::cout<<a<<" is constructed\n";}
    foo(foo &&from){a=std::move(from.a);std::cout<<a<<" is moved\n";}
    foo(const foo& from){a=from.a;std::cout<<a<<" is copied\n";}
    foo& operator=(const foo&from){
        std::cout<<a<<" is assigned by "<<from<<"\n";
        if(this == &from)return *this;
        a=from.a;
        return *this;
    }
    foo& operator=(foo &&from){
        std::cout<<a<<" is move-assigned by "<<from<<"\n";
        a=std::move(from.a);
        return *this;
    }
    friend std::ostream &operator<<(std::ostream&o,const foo&f){o<<f.a;return o;}
    operator int(){return a;}
    ~foo(){std::cout<<a<<" is destructed\n";}
};
int main(){
/*1*/std::vector<foo> vec = {0,0,1,2};
    std::cout<<"Go through:\n";
    std::cout<<"Capacity:"<<vec.capacity()<<std::endl;
    for(auto& v:vec) /*printf("%d\n",v);*/std::cout<<v<<std::endl;
    std::cout<<"Erase:\n";
    for(std::vector<foo>::iterator iter=vec.begin();
 /*2*/   iter!=vec.end();/*iter++*/){
        if(*iter == 0){
            std::cout<<"Erasing:\n";
/*3*/         vec.erase(iter);
            std::cout<<"Erased.\n";
       }
        else/* printf("%d\n",*iter);*/std::cout<<*iter++<<",";
    }
    std::cout<<"\nGo through again:\n";
    std::cout<<"Capacity:"<<vec.capacity()<<std::endl;
    for(auto& v:vec) /*printf("%d\n",v);*/std::cout<<v<<std::endl;
    std::cout<<"Swapping:\n"<<std::endl;
/*4*/    std::vector<foo>(vec).swap(vec);
    std::cout<<"Capacity after swapping:"<<vec.capacity()<<std::endl;
   return 0;
}

運行情況如下(在VS 2010 和 VS 2017上跑會出錯,在Linux下沒問題。不知道爲什麼這篇文章不能繼續加字了。。。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章