STL組件概述

一、六大組件
容器、類屬算法、迭代器、函數對象、適配器、分配器

二、容器(存儲其他對象集合的對象)
1.序列容器(將一組具有相同類型的對象以嚴格線性的形式組織在一起)
  • vector<T>:隨機訪問編程序列,即:訪問複雜度爲O(1),對序列末尾的插入和刪除均是分攤常量;(數組表示
  • deque<T>:隨機訪問邊長序列,對序列開頭和末尾的插入和刪除操作均是分攤常量的;(兩級數組結構實現
  • list<T>:(雙向鏈表)對變長序列的線性時間訪問;對序列中任意位置的插入和刪除操作時間複雜度爲O(1);(雙向鏈表實現
:(1)對於string類和STL序列容器類,其end成員函數返回的是終點之後的迭代器,而不是真正指向序列最後一個元素的迭代器;
(2)STL爲所有容器類都定義了==運算符;

2.有序關聯容器(有從基於鍵的集合中快速提取對象的能力,集合的大小可運行時改變)
  • set<Key>:支持唯一的鍵(每個鍵只出現一次),並可快速檢索鍵;
  • multi<Key>:支持可重複的鍵(同一個鍵可出現多次),可快速檢索鍵key 
  • map<Key,T>:鍵值對,支持唯一的鍵可通過鍵快速檢索其對應的類型爲T的值;(用find(Key)數據成員實現)
  • multimap<Key,T>:鍵值對,支持可重複的鍵;可通過鍵快速檢索其對應的類型爲T的值;
例,向map中插入元素:
map<string , long> map_test;
map_test["cyj"]=123;

注意:STL容器和其他C++容器類庫的重要區別之一:STL容器類並沒有爲其所含的數據提供過多的操作,而是提供了類屬算法

三、類屬算法
1.類屬查找算法(適用於任何STL容器)
  • find(iterator1 , iterator2, search_content):若找到,返回第一個出現search_content的位置,否則返回容器某位元素後面一個元素的迭代器;
    例:
    vector<char> vec1 = make<vector<char> >("C++");
    find(vec1.begin|(),vec1.end(),'C');
注:與表(list)對應的迭代器不支持+運算符,支持自增預算符++;所有STL容器均支持自增預算符++

2.類屬合併算法(merge,將兩個序列內的元素合併到一個序列中)
  • 調用形式
    merge(  first1 , last1 , first2 , last2, result );
    (1) 迭代器first1和last1表示一個輸入序列的起始和終止位置,元素類型爲T;
    (2)迭代器first2和last2表示另一個輸入序列的起始和終止位置,元素類型爲T;

    (3)兩個輸入序列均爲升序排列

    (4)result表示合併序列存放的起始位置注意:結果容器所有元素均升序排列;若前面兩個容器中元素均未升序排列,合併後的result容器非升序排列;三個容器不一定是同一類容器,可以屬於不同類別,如:分別爲list,char[] , deque容器,但元素類型必須爲T;
例子:
#include <cassert>
2 #include <iostream>
3 #include <deque>
4 #include <list>
5 #include <algorithm>
6 #include "string.h"
7 #include "stdlib.h"
8 using namespace std;

10 template<typename container>
11 container make( const char source[]);
12 
13 int main()
14 {
15 char s[]="acd";(升序)
16 int len = strlen(s);
17 list<char> list1 = make< list<char> >("befghijklmnopqrstuvwxy");(升序)
18 deque<char> d(26,'x');
19 
20 merge(&s[0],&s[len] , list1.begin() , list1.end(),d.begin());
assert( d == make< deque<char> >("abcdefghijklmnopqrstuvwxyx"));
23 std::cout<<"result ok"<<std::endl;
24 return 0;
25 }
26 
27 
28 template<typename container>
29 container make( const char source[])
30 {
31 return container( &source[0] , &source[strlen(source)]);
32 }


四 迭代器(具有和指針類似的特徵)


1.迭代器分類
  • 輸入迭代器:支持!=,*,++,==,但是對於*操作,只能從容器中讀取數據,而不能向其中寫入數據
  • 輸出迭代器:支持!=,*,++,==,但是對於*操作,不能從容器中讀取數據,只能向其中寫入數據
  • 前向迭代器:支持==,!= , *,++操作;
  • 雙向迭代器:支持==,!= , *,++,--操作;
  • 隨機訪問迭代器:支持==,!= , *,++,--,+=,-=,+,-,<,>,<=,>=操作
  • 類屬函數accumulate:accumulate(first,last,init),把init和從first到last指向的值進行累加並返回累加得到的和;
注意:accumulate、find、merge等一些用於輸入地帶器的算法比對迭代器有更高要求的算法(如sort算法要求使用隨機訪問迭代器)通用性強。


五、函數對象
  • 函數對象:一個實體,可以不帶參數,也可以帶有一個以上的參數,並能夠從中獲得一個值或改變程序的狀態,除了普通函數,另一類函數對象可以是類或結構的對象,且在其定義中重載了函數調用運算符
例子:
#include <iostream>
2 #include <vector>
3 #include <algorithm>
4 #include <numeric> //for accumulate

6 using namespace std;
7
//函數對象,重載函數調用運算符。
8 class multi{
9 public:
10 //function call overload
11 int operator()(int x , int y ) const
12 {
13 return x*y;
14 }
15 };
16 
17 int main()
18 {
19 int x[5]={1,2,3,4,5};
20 vector<int> vec1(&x[0],&x[5]);
//1 is inited value
22 int result = accumulate(vec1.begin() , vec1.end() , 1, multi());
23 std::cout<<"result is:"<<result<<std::endl;
24 }

  • 在類multi中定義函數調用運算符operator(),就定義了一種可以作爲函數參數的對象,可以像使用函數一樣使用該對象;multi()使用編譯器提供的默認構造函數;該對象沒有響應的內存,只有函數定義;
  • 函數對象的優勢
    (1)以類的形式定義函數對象,可以攜帶更多額外信息,某些類屬算法或容器將會用到這類信息;
    (2)更加通用、高效

六、適配器(改變其他組件接口的組件)
  • 適配器reverse_iterator:將某種類型的迭代器變成一種新的迭代器,但保持其功能不變,將其遍歷的方向翻轉過來。(使用場景:如用find函數查找某個元素在容器中最後出現的位置;浮點數累加,若元素升序排列,舍入誤差通常會小一些,否則,以降序順序排列時,與累加和相比,非常小的數值對於累加和幾乎不起任何作用,因此可用reverse_iterator和accumulate實現降序序列浮點數累加,結果精確些)
  • 注:STL每種容器都定義了reverse_iterator,以及返回這種類型迭代器的rbegin和rend成員函數
  • 棧適配器:將序列容器變換到先進後出的棧接口中;
  • 隊列適配器:將序列容器變換到先入先出隊列中;
  • 優先級隊列:將序列容器變換到優先級隊列中,由一個比較參數來控制元素訪問順序。
  • 函數適配器:
    (1)取反器(negator):對判定函數對象(返回值爲bool類型)的結果進行取反;
    (2)綁定器(binder):將二元函數的一個參數與某個特定的值綁定,從而將二元函數編程一元函數。
    (3)函數指針適配器:從函數指針得到函數對象。

七、分配器(封裝程序所用的內存分配模式信息)
注:分配器類可以封裝許多信息:指針、常量指針、引用、常量引用、對象大小、不同類型指針之間的差別、分配函數與釋放函數以及其他一些函數信息。分配器上所有操作都具有分攤常量的運行時間
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章