
- C++ 基礎
- C++ 首頁
- C++ 概述
- C++ 環境搭建
- C++ 基本語法
- C++ 註釋
- C++ Hello World
- C++ 省略名稱空間
- C++ 常量/字面量
- C++ 關鍵字
- C++ 識別符號
- C++ 資料型別
- C++ 數值資料型別
- C++ 字元資料型別
- C++ 布林資料型別
- C++ 變數型別
- C++ 變數作用域
- C++ 多個變數
- C++ 基本輸入/輸出
- C++ 修飾符型別
- C++ 儲存類
- C++ 運算子
- C++ 數字
- C++ 列舉
- C++ 引用
- C++ 日期和時間
- C++ 控制語句
- C++ 決策
- C++ if 語句
- C++ if else 語句
- C++ 巢狀 if 語句
- C++ switch 語句
- C++ 巢狀 switch 語句
- C++ 迴圈型別
- C++ while 迴圈
- C++ for 迴圈
- C++ do while 迴圈
- C++ foreach 迴圈
- C++ 巢狀迴圈
- C++ break 語句
- C++ continue 語句
- C++ goto 語句
- C++ 建構函式
- C++ 建構函式和解構函式
- C++ 複製建構函式
C++ STL 教程
希望您已經理解了我們之前討論過的 C++ 模板的概念。C++ STL(標準模板庫)是一套強大的 C++ 模板類,它使用模板提供通用類和函式,實現了許多流行且常用的演算法和資料結構,例如向量、列表、佇列和棧。
C++ 標準模板庫的核心是以下三個結構良好的元件:
序號 | 元件及描述 |
---|---|
1 | 容器 容器用於管理特定型別的物件的集合。有幾種不同型別的容器,例如 deque、list、vector、map 等。 |
2 | 演算法 演算法作用於容器。它們提供了執行容器內容初始化、排序、搜尋和轉換的方法。 |
3 | 迭代器 迭代器用於遍歷物件集合的元素。這些集合可能是容器或容器的子集。 |
我們將在下一章討論 C++ 標準庫時討論所有三個 C++ STL 元件。現在,請記住所有三個元件都有一套豐富的預定義函式,這些函式可以幫助我們以非常簡單的方式完成複雜的任務。
示例
讓我們來看以下程式,它演示了 vector 容器(一個 C++ 標準模板),它類似於陣列,區別在於它在增長時會自動處理自己的儲存需求:
#include <iostream> #include <vector> using namespace std; int main() { // create a vector to store int vector<int> vec; int i; // display the original size of vec cout << "vector size = " << vec.size() << endl; // push 5 values into the vector for(i = 0; i < 5; i++) { vec.push_back(i); } // display extended size of vec cout << "extended vector size = " << vec.size() << endl; // access 5 values from the vector for(i = 0; i < 5; i++) { cout << "value of vec [" << i << "] = " << vec[i] << endl; } // use iterator to access the values vector<int>::iterator v = vec.begin(); while( v != vec.end()) { cout << "value of v = " << *v << endl; v++; } return 0; }
當以上程式碼編譯並執行時,會產生以下結果:
vector size = 0 extended vector size = 5 value of vec [0] = 0 value of vec [1] = 1 value of vec [2] = 2 value of vec [3] = 3 value of vec [4] = 4 value of v = 0 value of v = 1 value of v = 2 value of v = 3 value of v = 4
以下是一些關於我們在上述示例中使用的各種函式需要注意的事項:
- push_back() 成員函式在向量的末尾插入值,根據需要擴充套件其大小。
- size() 函式顯示向量的尺寸。
- begin() 函式返回指向向量開頭的迭代器。
- end() 函式返回指向向量末尾的迭代器。
C++ 標準模板庫元件
C++ 標準模板庫的核心是以下四個結構良好的元件:
- 容器
- 演算法
- 迭代器
- 仿函式(函式物件)
容器
容器是用於儲存和管理資料或物件集合(例如向量、列表、集合和對映)的資料結構。在這裡,我們將看到幾種型別的容器。
1. 順序容器
它們是按特定線性順序儲存元素的容器。它們允許直接訪問元素以及管理元素順序和排列的功能。
- 陣列 − 這些是固定大小的元素集合。
- 向量 − 它是一個動態陣列,可以根據需要調整其大小。
- 雙端佇列 − 雙端佇列,允許在兩端快速插入和刪除。
- 列表 − 一個雙向連結串列,允許雙向迭代。
- 前向列表 − 它是一個單向連結串列,允許高效插入和刪除,但只能單向遍歷。
- 字串 − 在 C++ 中,字串也被認為是順序容器,它被實現為字元的動態陣列,其行為類似於其他順序容器。
2. 關聯容器
它以排序的順序儲存元素,允許根據鍵快速檢索。這些容器以鍵值對結構工作,其中每個元素都與一個唯一的鍵關聯。此鍵用於快速訪問相應的鍵值。
3. 無序關聯容器
它以無序的方式儲存元素,允許根據鍵高效訪問、插入和刪除。它們不維護元素的排序順序,而是使用雜湊來組織資料。
- 無序集合 − 它是一組唯一的元素,沒有任何特定順序。
- 無序對映 − 它是一組鍵值對,沒有任何特定順序。
- 無序多重集 − 它允許重複元素,沒有任何特定順序。
- 無序多重對映 − 它允許重複鍵,沒有任何特定順序。
4. 容器介面卡
它為現有容器提供不同的介面。
演算法
C++ 標準模板庫 (STL) 中的演算法是一個大型函式集合,專門設計用於對容器執行操作。其中,這些演算法使用迭代器來遍歷容器,而無需瞭解其內部結構。
非修改順序演算法
- for_each − 它應用於查詢範圍內的每個元素的函式。
- count − 它計算範圍內某個值的出現次數。
- find() − 它查詢範圍內某個值的第一次出現。
- find_if − 它查詢滿足謂詞的第一個元素。
- find_if_not − 它查詢不滿足謂詞的第一個元素。
- equal − 它檢查兩個範圍是否相等。
- search − 它在一個序列中搜索子序列。
1. 修改順序演算法
- copy() − 它將元素從一個範圍複製到另一個範圍。
- copy_if − 它將滿足謂詞的元素複製到另一個範圍。
- copy_n − 它將特定數量的元素從一個範圍複製到另一個範圍。
- move − 它將元素從一個範圍移動到另一個範圍。
- transform() − 它將函式應用於範圍並存儲結果。
- remove − 它從範圍內刪除具有特定值的元素。
- remove_if − 它刪除滿足謂詞的元素。
- unique − 它刪除連續的重複元素。
- reverse() − 它反轉範圍內元素的順序。
- swap() − 它交換元素。
2. 排序演算法
- sort − 它對範圍內的元素進行排序。
- stable_sort − 它對元素進行排序,同時保持等效元素的相對順序。
- partial_sort − 它對範圍的一部分進行排序。
- nth_element − 它對範圍進行分割槽,以便第 n 個元素位於其最終位置。
3. 搜尋演算法
- binary_search − 它檢查元素是否存在於排序範圍內。
- lower_bound − 它搜尋可以插入元素以保持順序的第一個位置。
- upper_bound − 它搜尋大於指定值的第一個元素的位置。
- binary_search − 它檢查元素是否存在於排序範圍內。
- lower_bound − 它查詢可以插入元素以保持順序的第一個位置。
- upper_bound − 它搜尋大於指定值的第一個元素的位置。
- equal_range − 它返回相等元素的範圍。
4. 堆演算法
- make_heap − 從一個區間建立堆。
- push_heap − 向堆中新增一個元素。
- pop_heap − 從堆中刪除最大元素。
- sort_heap − 對堆中的元素進行排序。
5. 集合演算法
- set_union − 計算兩個集合的並集。
- set_intersection − 計算兩個集合的交集。
- set_difference − 計算兩個集合的差集。
- set_symmetric_difference − 計算兩個集合的對稱差集。
6. 數值演算法
- accumulate − 計算一個區間的和(或其他操作)。
- inner_product − 計算兩個區間的內積。
- adjacent_difference − 計算相鄰元素之間的差。
- Partial_sum − 計算一個區間的部分和。
7. 其他演算法
- generate − 使用函式生成的值填充一個區間。
- shuffle − 隨機打亂一個區間內的元素。
- partition − 根據謂詞將元素劃分為兩組。
迭代器
C++ 標準模板庫 (STL) 中的迭代器是充當容器內元素指標的物件,它提供了一個統一的介面來訪問和操作資料。它們充當演算法和容器之間的橋樑。
函式物件(仿函式)
C++ 中的仿函式(或函式物件)是可以像函式一樣呼叫的物件。它可以像普通函式一樣被呼叫。此功能是透過過載函式呼叫運算子()來實現的。
在這裡,您將根據它們執行的操作探索不同型別的仿函式。
1. 算術仿函式
在 C++ 中,算術運算子用於執行基本的數學運算。以下是常見的算術運算子以及示例。
- 加法 (+) − 將兩個值組合起來以產生它們的和。
- 減法 (-) − 計算兩個值之間的差。
- 乘法 (*) − 將兩個值相乘以產生它們的積。
- 除法 (/) − 將一個值除以另一個值,得到商。
- 模 (%) − 返回一個值除以另一個值的餘數。
- 取反 (-) − 返回引數的取反值。
2. 比較仿函式
比較仿函式用於比較值,尤其是在容器中進行排序或搜尋時。
- 小於 (<) − 比較並返回第一個值是否小於第二個值。
- 大於 (>) − 比較並返回第一個值是否大於第二個值。
- 小於等於 (≤) − 比較並返回第一個值是否小於等於第二個值。
- 大於等於 (≥) − 比較並返回第一個值是否大於等於第二個值。
- 等於 (=) − 比較並返回兩個值是否相等。
- 不等於 (≠) − 比較並返回兩個值是否不相等。
3. 邏輯仿函式
邏輯仿函式執行邏輯運算,在涉及布林邏輯的場景中可能很有用。
- 邏輯與仿函式 (&&) − 如果兩個布林引數中至少有一個或兩個為假,則返回假,否則返回真。
- 邏輯或仿函式 (||) − 如果兩個布林引數中至少有一個或兩個為真,則返回真。
- 邏輯非仿函式 (!) − 如果布林引數為假則返回真,反之亦然,它返回提供布林值的相反值。
4. 位運算仿函式
- bit_and − 對兩個運算元執行按位與運算。
- bit_or − 對兩個運算元執行按位或運算。
- Bit_xor − 對兩個運算元執行按位異或 (XOR) 運算,並返回相應的輸出。
實用工具
實用工具是指一系列通用元件,它們在程式設計中提供基本功能,並允許對資料和型別進行高效操作。
1. 對和元組
- pair − 它是一個容器,包含兩個可能不同型別的值,作為第一個和第二個成員。
- tuple − 一個固定大小的集合,可以儲存多種不同型別的多個值,可以透過 std::get 訪問每個元素。
2. 智慧指標
- unique_ptr − 它是一個智慧指標,擁有一個動態分配的物件,當指標超出範圍時會自動釋放它。
- Shared_ptr − 它是一個智慧指標,允許多個指標共享一個動態分配物件的擁有權,透過使用引用計數來管理生命週期。
- Weak_ptr − 它是一個智慧指標,提供對由 std::shared_ptr 管理的物件的非擁有引用,這可以防止迴圈引用。
3. 可選、變體和任何型別 (C++17)
- Optional − 它是一個包裝器,表示一個可選的值,指示值是否存在。
- variant − 它是一個型別安全的聯合,可以儲存多個指定型別之一,提供了一種在不產生歧義的情況下處理多種型別的方法。
- any − 它是一個型別安全的容器,用於儲存任何型別的值,允許動態型別擦除和執行時型別檢查。
4. 記憶體管理和數值限制
- allocator − 用於管理動態記憶體。
- numeric_limits − 提供有關基本資料型別屬性的資訊。
5. 型別特徵
它是一組模板,允許您執行編譯時型別檢查。
- is_same − 它是一個型別特徵,檢查兩個型別是否相同,如果相同則返回真,否則返回假。
- is_integral − 它是一個型別特徵,確定給定型別是否為整型(例如,int、char、long),對於整型返回真,對於其他型別返回假。
- is_floating_point − 它是一個型別特徵,檢查給定型別是否為浮點型別(例如,float、double、long double),對於浮點型別返回真,對於非浮點型別返回假。
- enable_if − 它是一個實用工具,根據編譯時條件啟用或停用模板例項化,通常用於 SFINAE(替換失敗不是錯誤)。
基本 STL 功能:簡單示例
這是一個演示一些基本 STL 功能的簡單示例
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {5, 2, 8, 1, 3}; // Sorting the vector std::sort(vec.begin(), vec.end()); // Displaying sorted elements std::cout << "Sorted vector: "; for (int num : vec) { std::cout << num << " "; } std::cout << std::endl; // Finding an element auto it = std::find(vec.begin(), vec.end(), 3); if (it != vec.end()) { std::cout << "Element 3 found at position: " << std::distance(vec.begin(), it) << std::endl; } else { std::cout << "Element 3 not found" << std::endl; } return 0; }
輸出
Sorted vector: 1 2 3 5 8 Element 3 found at position: 2
解釋
此程式碼在多個地方提供了 STL 的使用,
- std::vector<int> vec − 上述程式使用了 std::vector,它是一個 STL 容器,允許動態陣列管理。
- std::sort(vec.begin(), vec.end()) − 此函式是 STL 演算法的一部分,它作用於容器,按升序對向量的元素進行排序。
- std::find(vec.begin(), vec.end(), 3) − 此函式在向量中搜索值 3,如果找到則返回指向它的迭代器。
- begin() 和 vec.end() − 這些函式分別返回指向向量開頭和向量末尾之後的迭代器。
- std::distance(vec.begin(), it) − 此函式計算兩個迭代器之間的元素數量(在本例中,從向量的開頭到找到的迭代器),有效地給出找到的元素的索引。
使用 STL 的好處
在 C++ 中使用標準模板庫 (STL) 有很多好處,因為它提供了一個龐大的預定義資料結構和演算法集合,從而節省了時間和精力,減少了從頭實現這些結構和演算法的需要。它還促進了程式碼重用、模組化、型別安全和靈活性。這使得相同的程式碼可以與不同的資料型別一起工作。總的來說,它提高了程式設計效率和程式碼質量。