C++容器基礎之vector

一、vector概述

    vector是線性容器,元素按照線性順序排序,容器中元素存儲在一塊連續的內存中,類似與數組,不過vector可以自動增長或縮小存儲空間。

   與數組相比:在自動處理容量的大小時會消耗更多的內存,當時vector可以提供和數組一樣的性能,並且可以很好的調整存儲空間的大小。

    和其他標準的順序容器相比:vector可以更有效的訪問容器內元素,和在末尾添加、刪除元素;而在其他位置的添加刪除元素,vector不如其他順序容器。

    注意:size()返回容器的大小,大小指的是當前容器中元素的個數,cacapacity()返回的是容器的容量,容量指的是已經分配的內存的大小。

 

二、vector的使用

1、初始化和遍歷

    //三種遍歷方式
    //1、下標
    for(int i=0; i<vec.size(); i++){
        cout << vec[i] << ", ";
    }
    cout << endl << "---------" << endl;
    //2、迭代器
    for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++){
        cout << *it << ", ";
    }
    cout << endl << "---------" << endl;
    //3、for each
    for(int temp : vec){
        cout << temp << ", ";
    }

其中,vec.begin()指的是vec中第一個元素的迭代器,vec.end()指的是最後一個元素的下一個位置。 

2、vector的排序

兩種方式:1)如果存放的是自定義對象,則可以在類中實現<運算符,然後使用sort函數進行比較;2)自定義比較函數,在使用sort函數的時候,將比較函數當作參數傳入其中。其中,sort函數是算法中的函數,頭文件是algorithm。

3、查找

可以使用算法中的find函數,頭文件是algorithm。如果存在則返回迭代器,否則返回vector.end()。

4、刪除

三種方式:1)pop_back(),刪除最後一個元素;2)erase()刪除指定元素;3)clear(),刪除所有元素,清空。

erase()有兩種形式:

  • iterator erase(iterator position)
  • iterator erase(iterator first, iterator last)

使用erase的時候要注意迭代器失效的問題。

for(auto it = vec.begin(); it != vec.end(); it++){
    if(*it == 3){
        vec.erase(it);
    }
}

此代碼是錯誤的,當刪除it的時候,it就變成了野指針,無法進行++操作的。

for(auto it = vec.begin(); it != vec.end(); it++){
    if(*it == 3){
        it = vec.erase(it);
    }
}

此代碼也是錯誤的:1)無法刪除連續的3;2)當3位於vector的末尾,刪除的時候也會出錯(在vec.end()上執行了++操作)。

for(auto it = vec.begin(); it != vec.end(); ){
    if(*it == 3){
        it = vec.erase(it);
    }else{
        ++it;
    }
}

 這纔是正確的刪除方式。

5、添加

有兩種方式:1)insert,是在指定位置添加元素;2)push_back,是在最後添加元素

insert有三種形式:

  • iterator insert(iterator pos, const TYPE &val)//在pos前插入val,返回這個元素的迭代器
  • void insert(iterator pos, size_type num, const TYPE &val)//在pos前插入num個val元素
  • void insert(iterator pos, input_iterator start, input_iterator end)//在pos前,插入[start, end)區間中的元素

 

三、小技巧

1、使用reserve ()函數提前設定容量大小

    vector支持隨機訪問,爲了提高效率,採用動態數組實現。在通過reserve函數來申請特定大小的內存空間的時候,總是按照指數邊界來增大其內部緩衝區的。當進行insert或者push_back操作時,如果空間不夠用,則會重新分配當前大小的1.5~2倍的新內存區,然後再把原來的內容複製過去。所以,當重新分配的操作發生時,其性能纔會下降。

    所以,如果有大量的數據進行添加的時候,應當使用reserve()函數提前設定其容量大小,否則會出現多次容量擴大的操作,導致效率低下。

比如,如果要存儲1000個數據,可以這樣做:

vector<int> vec;
vec.reserve(1000);
for(int i = 0; i < 1000; i++)
    vec.push_back(i)

2、使用“交換”來調整vector過剩空間

    有一種方法來把它從曾經最大的容量減少到它現在需要的容量,這樣的方法常常被稱之爲“收縮到合適”(shrink to fit)。

    該方法只需要一條語句:vector<int>(ivec).swap(ivec)。

    vector<int>(ivec)表示建立一個臨時的vector,它是ivec的一份拷貝。但是vector的拷貝構造函數只分配拷貝元素所需要的內存,也就是說這個臨時的vector沒有多餘的空間。然後臨時的vector和ivec進行交換數據,但是ivec只有臨時變量的修正過的容量,而這個臨時變量則持有了ivec曾經沒有用到的容量。在這條語句的結尾處,臨時vector被銷燬,釋放之前ivec使用的內存,而相應的ivec收縮到合適大小。

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