跟我學C++中級篇——STL的學習

fpcc發表於2021-01-01

 

一、c++標準庫

C++的標準庫主要包含兩大類,首先是包含C的標準庫的,當然,為了適應c++對一些C庫進行了少許的修改和增加。最重要的當然是物件導向的c++庫;而c++庫又可以分成兩大類,即物件導向的c++庫和標準模板庫,也就是題目中的STL。另外在此基礎上,還要提醒同學們的是,除了上面的庫,在各個平臺的開發廠商中,還會針對實際情況,對標準庫進行擴充套件,這些可以歸納為擴充套件庫。
同時,隨著c++標準的不斷迭代,還推出了很多新的庫,同學們需要不斷的學習跟進,目前最新的c++標準為c++20。主流的c++標準庫實現有GNU/Linux上的libstdc++;IOS的libc++;微軟的CRT,android的libc++,當然在NDK有過很多c++的版本,不過後來都被刪除了;其它包括uSTL,Apache等很多大公司也有自己的相關的c++庫(這裡就不能叫標準庫了,雖然實現的目的是一樣的)。下面是相關庫的基本組成部分分類:

c庫主要包括:
1、標準輸入輸出,比如stdin,stdout,stderr。
2、字串處理,比如strcat,strcopy等。
3、記憶體管理,如果malloc等。
4、日期、時間和本地化等如ctime,time,localtime等。
5、數學相關函式,如pow,cos等。
6、系統和管理相關函式,它定義了和OS相關的訊號和函式呼叫規則,如setjmp,va_start等。
7、異常和錯誤,最典型的就是errno。
8、其它輔助如一些巨集定義等。

c++庫主要包括:
1、標準的IO類,如std::cout,std::in,ofstream等。
2、必須要提到的std::string。
3、數值處理相關類,numeric的complex。
4、本地化庫。
5、異常庫。
6、其它。
7、STL(標準模板庫)。

在後面的學習應用中將以STL為主,穿插學習標準庫的其它用法。

二、STL主要分類

STL標準模板庫主要分類:
1、STL容器(Containers),包含順序容器和關聯容器以及無序容器
容器非常好理解,日常的容器可以盛納各種液體和物品。而在STL的容器可以盛納各種資料。它分為順序容器和關聯容器兩大類,順序容器是指讀寫按照容器內的元素位置進行操作。你可以理解成一個箱子裡有好多小格子,你可以根據小格子的順序來取到其中的內容。它主要包括向量(Vector),連結串列(List)和雙端佇列(deque);而關聯容器則是需要通過一個鍵值(KEY)來讀寫容器的元素。在標準庫裡主要就是對映(map)和集合(set)。無序容器主要包括unordered_set和unordered_map。

2、STL迭代器(Iterators)
迭代器其實更好理解,就是一種可以通用在容器中的遍歷訪問的模板指標。就是一個資料訪問的索引。

3、STL分配器(Allocators)
分配器其實就是為了方便對容器等的通用化記憶體管理,提供的一種記憶體分配管理機制,可以理解成一種STL中的記憶體池。

4、STL介面卡(Adapters)
介面卡這個概念有點意思,其實如果有過介面開發經驗的可能更容易明白,兩種不同的介面要想使用同一個資料體系,就需要寫一個小模組來進行介面資料的統一,這個小模組就叫做介面卡。它其實是一種設計模式,而這種思想體現在STL中,就成為了介面卡。

5、STL仿函式(函式物件)(Functors)
仿函式,有的翻譯成函式物件,這個更有意思,其實就是通過前面提到的過載運算子(),實現了類似於函式使用的機制。在c++11後,提供了更安全的std::function。

6、STL演算法(Functors)
模板庫最初其實就是為了實現演算法而設計的,這個在《c++程式設計思想》中的“通用演算法”中有過提及。演算法可能是同學們最容易理解但最不容易掌握的一部分了。比如常見的查詢,排序以及刪除、複製等。

除了上面這些基礎的分類,在c++的新版本中又增加了概念等相關的知識,有興趣可以看看本公眾號中c++20的新功能相關文章。

三、例程

後面會對這些STL的基本容器和演算法逐一進行分析,這裡給出一個綜合例子:

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <array>

#include <algorithm>

struct Data
{
    int len = 0;
    int type = 0;
};
//類似陣列
void TestVector()
{
    std::vector<Data> vec;
    Data d1;
    Data d2;
    vec.emplace_back(d1);
    vec.push_back(d2);
    std::cout << "vector first:" << vec[0].len << std::endl;
    std::cout << "vector size:" << vec.size() << std::endl;
}
//連結串列
void TestList()
{
    std::list<int> l;
    l.push_back(3);
    l.push_front(9);
    l.emplace_back(6);

    std::cout << "list first:" << l.front() << std::endl;
    std::cout << "list size:" << l.size() << std::endl;
}

//佇列
void TestQueue()
{
    std::queue<int> q;
    q.emplace(10);
    q.push(20);
    q.push(30);

    std::cout << "queue first:" << q.front() << std::endl;
    q.pop();
    std::cout << "queue first:" << q.front() << std::endl;
    q.pop();
    std::cout << "queue first:" << q.front() << std::endl;
    q.pop();
}

int buf[] = { 10,9,21,68,96,11,11,11,88,199,36,96,60,126,19,168 };
void TestSort()
{
    std::array<int, 16> arr = { 0,9,21,68,96,11,11,11,88,199,36,96,60,126,19,168 };
    std::sort(arr.begin(), arr.end());

    std::cout << " ordered reslut:" << std::endl;
    for (int num = 0; num < 16; num++)
    {
        std::cout << arr[num] << "  ";
    }

    std::cout << " " << std::endl;
}
void TestSearch()
{
    std::sort(buf,buf+16);
    bool result = std::binary_search(buf,buf+16, 199);
    std::cout << "search result:" << result << std::endl;

}
void TestCopy()
{
    int buf_dst[100] = {0};
    std::copy(buf,buf+16,buf_dst);
    std::cout << "copy result:" << std::endl;
    for (auto& au : buf_dst)
    {
        std::cout << au << "  ";
    }
    std::cout << " " << std::endl;
}
int main()
{
    TestVector();
    TestList();
    TestQueue();

    //排序
    TestSort();
    TestSearch();
    TestCopy();

    std::cout << "STL test project!" << std::endl;
}

執行結果是:

vector first:0
vector size:2
list first:9
list size:3
queue first:10
queue first:20
queue first:30
 ordered reslut:
0  9  11  11  11  19  21  36  60  68  88  96  96  126  168  199
search result:1
copy result:
9  10  11  11  11  19  21  36  60  68  88  96  96  126  168  199  0  0  0  0  
STL test project!

這裡仍然提醒注意的是,新標準在快速迭代,要注意更新標準的知識。

四、注意點

1、c++標準庫不是萬能的,有些庫其實並不多受歡迎,比如標準輸入輸出的流操作。
2、c++標準庫使用不復雜,但內部機制越來越複雜,特別模板機制,本身就是一個複雜而又困難的事情。而新標準中增加的協程等更是提高了內部實現的複雜度。
3、c++標準從c++11迭代的速度明顯加快,要注意新版本的更新和跟進。

五、總結

在STL的學習過程中,會把相關的原始碼解析也會展開一部分,這樣,既可以更好的瞭解庫的內部實現,又容易理解庫的應用情況。STL是學c++的人繞不過去的庫,不想用,不代表不需要。

 

相關文章