C++primer 第九章筆記 初稿

9.1 順序容器

  1. 性質:容器中元素的順序與加入的位置相對應,爲使用者提供了控制元素存儲和訪問順序的能力。
  2. 六大順序容器

    名稱 功能 特點>
    vector 可變大小數組 支持快速隨機訪問,除尾部外插入、刪除較慢
    deque 雙端隊列 支持快速隨機訪問,頭尾外插入刪除較慢
    list 雙向列表 支持雙向順序訪問,任何位置插入刪除很快
    forward_list 單項列表 支持正向順序訪問,任何位置插入刪除很快
    array 固定大小數組 支持快速隨機訪問,不能添加刪除
    string 字符串 支持快速隨機訪問,除尾部外插入、刪除較慢
  1. list與forward_list相較有更大的額外內存消耗。
  2. array相比內置數組更爲安全。
  3. 標準庫運行效率較高,應當優先選擇標準庫而不是原式數據結構。
  4. 如果程序只要在讀取時纔會向容器中間插入數據,可以設定一個list緩衝。

9.2順序容器概覽(一般操作)

類型與函數 描述
iterator 迭代器
const_iterator 只讀迭代器
size_type 無符號整型,描述容器大小或迭代器位置差
difference_type 帶符號整型
value_type 元素類型
reference 元素左值類型,與value_type&相似
const_reference const左值
C c, C c(c2), C c(b,e) 構造函數
C c{a,b,c,d…} 構造函數
C c(n), C c(n,t) 構造函數,n爲個數,t爲初始值
c1=c2, c1={a,b,c,d,…} 賦值
a.swap(b), swap(a,b) 交換
c.size() 元素個數(不支持forward_list
c.max_size() 容器可保存最多元素個數
c.empty() 確認容器是否爲空
c.insert(args) 插入元素
c.emplace(inits) 構造一個元素
c.erase(args) 刪除元素
c.clear() 清空容器
reverse_iterator 逆尋址迭代器
const_reverse_iterator 只讀逆尋址迭代器
c.rbegin(), c.rend(), c.crbegin(), c.crend 返回逆尋址迭代器

對於C c(b,e)的構造方法,C所聲明的容器元素類型,必須與b e的類型相容(不一定一樣,除array)。

比較運算符必須要求容器中的元素允許元素運算。

  1. 迭代器有公共的接口,forward_list不支持自減操作。

  2. 對反向迭代器使用自增,等價於正向迭代器遞減。

  3. 迭代器初始化與拷貝初始化區別

    list<string> ls;
    vector<const char*> vcc;
    
    list<string> ls2(ls);//正確無疑
    deque<string>ds(ls);//錯誤,容器種類不同 
    vector<string>vs(vcc)//錯誤,容器元素類型不同
    forward_list<string>fs(vcc.begin(),vcc.end());//正確 
  4. array
    • 支持容器直接拷貝(內置數組當然不行),但是類型和長度必須都一致。
    • 不支持assign與列表賦值。

9.3 順序容器操作

  1. 賦值與交換

    • 交換兩個容器的元素通常比拷貝元素快,除array不涉及任何元素拷貝、刪除、插入,故在常數時間完成。

    • 賦值會導致左值容器的迭代器、引用、指針失效,而交換會導致所有迭代器、引用、指針失效(array,string除外)。

    • assign

      • assign(b,e):b和e不能是調用容器的迭代器。
      • assign(n,t):全部替換,沒有部分替換的方法。
    • 交換兩個array用線性時間,但是元素值改變的同時迭代器所表示的位置不變。

  2. 添加元素

    • push_back()

      • 不支持forward_list。
      • 本質是添加拷貝。
      • 返回void。
    • push_front

      • 支持list,forward_list,deque。
      • 在最開頭插入元素,返回void。
    • insert

      • 對push_front不支持不代表對insert插入開頭不支持。

      • 在迭代器指向元素之前插入,且返回第一個插入元素的迭代器。

      • 通過將返回值賦值給原迭代器,可實現在同一位置反覆插入元素。

      • 也有返回void版本的insert方法。

    • emplace :直接進行初始化
  3. 訪問元素

    • front:返回首元素的引用,通過*(c.begin())也可得到。

    • back:返回尾元素的引用,forward_list無,通過*(c.end()-1)也可得到。

    • at(n):返回下標爲n的元素的引用。
  4. 刪除元素

    • pop_front, pop_back

      • pop_back不支持forward_list,pop_front不支持vector、string。

      • 分別刪除首元素與尾元素,容器不可爲空,返回void。

    • erase:

      • 刪除單個或範圍元素,返回被刪除的最後一個元素之後的迭代器。

      • 刪除單個尾後迭代器是未定義的,範圍包含尾後迭代器是可以的。

    • forward_list

      • 特殊原因:作爲單向鏈表,無法通過簡答方法獲得元素的前驅,故通過改變給定元素之後的元素來實現。
      • insert_after:返回指向最後一個插入元素的迭代器。

      • emplace_after(p,args):插入元素args,返回指向插入元素的迭代器。

      • erase_after(p):刪除p指向位置之後的元素,返回指向被刪除元素之後的迭代器。
      • erase_after(b,e):刪除[b,e)之間的元素,且返回指向被刪除元素之後的迭代器。

      • 在forward_list中,通常會有兩個變量,一個記錄當前迭代器,一個記錄前驅迭代器。

        forward_list<int> fl = {0,1,2,3,4,5,6,7,8,9};
        auto prev=fl.before_begin();
        auto curr=fl.begin();
        while(curr!=fl.end()){
            if (*curr % 2)
                curr = fl.erase_after(prev);
            else
                prev = curr++;
        }
  5. 注意點:一旦涉及到容器的插入刪除,不要緩存迭代器(end()),應當每次使用都調用一次。

9.4 vector對象的增長方式

  • capacity:當前容器上限元素個數
  • reserve:給容器分配更大的空間(小於等於當前空間不會報錯,但是什麼也不做)
  • shrink_to_fit:將上限減少到與size()相匹配的大小。

  • vector重新分配內存時一般上限*2。

9.5 string的額外操作

  1. 構造方法

    • (cp,n)
      cp指向的數組中的,前n個元素的拷貝。如果不傳遞n,指針所指向的數組必須以 ‘\n’ 結尾!

    • (s2,pos2)
      從string類對象s2的下標pos2開始的拷貝,pos2大於s2.size()爲未定義的行爲。

    • (s2,pos2,len2)
      從string類對象s2的下標pos2開始len2個字符的拷貝,pos2大於s2.size()爲未定義的行爲,len2過長不影響正常運行。

    • s.substr(pos,n)
      返回字符串s從pos到pos+n-1的子串的拷貝。

  2. 其他操作

    • 存在基於下標運算的insert、erase、assign方法。

    • append(args):類似於”+”。

    • replace(range,args):range爲pos開始len長個字符,或者是一對迭代器。
    • 搜索操作

      • 返回值:string::size_type或string::npos。

      • find(args)
        返回調用對象中第一個匹配s的位置的下標,不存在則返回npos。

      • rfind(args)
        返回調用對象中最後一個匹配s的位置的下標,不存在則返回npos。
      • find_first_of(args)、find_last_of(args)
        返回第一次/最後一次args中任一字符出現的位置。
      • find_first_not_of(args)、find_last_not_of(args)
        返回第一次/最後一次不在args中出現的字符位置。
      • 樣例:查找數字字符
        
        #include <iostream>
        
        
        #include <cstring>
        
        using namespace std;
        
        int main(){
            string s="ab2c3d7R4E6";
            string sn="0123456789";
            string::size_type pos=0;
            while((pos=s.find_first_of(sn,pos))!=string::npos){
                cout<<s[pos]<<endl;
                pos++;
            } 
            pos=0;
            while((pos=s.find_first_not_of(sn,pos))!=string::npos){
                cout<<s[pos]<<endl;
                pos++;
            }
        
            return 0;
        } 
    • compare方法:類似於strcmp。

    • 數值轉換:一般爲sto + 類型首字母 + (s,p,b),p爲第一個非數值字符的下標,b爲基數默認10。
      string s="a=1";
      int i=stoi(s.substr(s.find_first_of(0123456789)));

9.6 順序容器適配器

  1. 定義:接受一種已有容器,並使其有接收適配器的操作。

  2. 定義適配器

    • 與容器定義類似。

    • 默認下,stack 和 queue 是基於deque實現的,而priority_queue是基於vector實現的。

    • 通過創建適配器時將命名的順序容器作爲第二個參數,可以重載默認容器類型。

      stack<string, vector<string>>str_stk(svec);
    • 限制

      • 適配器不能構造於array、forward_list之上。
      • queue不能構造於vector之上,priority_queue不能構造於list之上。
      • 適配器不可以調用底層容器專有的方法。
  3. 特徵

    • queue:先進先出,即進入隊列的對象被放置到對尾。
    • priority_queue:新加入的元素排在優先級比其低的元素之前。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章