首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

STL 學習系列之二:標準模板庫深度導覽 — 以 list 為核心範例

     編輯:關於C++

STL 三大核心組件

  1. 容器:資料結構封裝 (vector, list, set, map...)
  2. 演算法:通用操作 (sort, find, for_each...),透過迭代器作用於容器
  3. 迭代器:泛型指標抽象,定義演算法操作範圍 [first, last)

容器管理記憶體與存取介面,演算法實作邏輯,迭代器串聯兩者 — 這是泛型程式設計 (GP) 精髓。

list 容器完整操作教學

1. 定義與基本插入


#include 
#include 
using namespace std;

list milkshakes;
milkshakes.push_back("Chocolate");
milkshakes.push_back("Strawberry");
milkshakes.push_front("Lime");
milkshakes.push_front("Vanilla");
// 順序: Vanilla, Lime, Chocolate, Strawberry

2. 空檢查與大小


if (milkshakes.empty()) { /* ... */ }
cout << "大小: " << milkshakes.size() << '\n';

3. 遍歷:手動迭代器 vs for_each


// 手動
for (list::iterator it = milkshakes.begin(); it != milkshakes.end(); ++it)
    cout << *it << '\n';

// for_each + 函數物件
struct Print { void operator()(const string& s) { cout << s << '\n'; } };
for_each(milkshakes.begin(), milkshakes.end(), Print());

4. 計數:count / count_if


int n = count(milkshakes.begin(), milkshakes.end(), "Chocolate"); // 精確匹配

// count_if + 謂詞
struct IsChocolate { bool operator()(const string& s) { return s == "Chocolate"; } };
n = count_if(milkshakes.begin(), milkshakes.end(), IsChocolate());

5. 搜尋:find / find_if / search


auto it = find(milkshakes.begin(), milkshakes.end(), "Lime");
if (it != milkshakes.end()) cout << "找到: " << *it << '\n';

// find_if: 複雜條件
struct HasE { bool operator()(const string& s) { return s.find('e') != string::npos; } };
it = find_if(milkshakes.begin(), milkshakes.end(), HasE());

// search: 子序列
list target = {"Chocolate", "Strawberry"};
it = search(milkshakes.begin(), milkshakes.end(), target.begin(), target.end());

6. 排序:list::sort (非 std::sort)


list staff = {"John", "Bill", "Tony", "Fidel", "Nelson"};
staff.sort(); // 成員函數,merge sort,穩定
// 結果: Bill, Fidel, John, Nelson, Tony

原因:std::sort 需隨機存取迭代器,list 只提供雙向迭代器,故需專用 sort()。

7. 任意位置插入:insert


list nums;
for (int i=0; i<10; ++i) nums.push_back(i); // 0..9
nums.insert(nums.begin(), -1);               // -1, 0..9
nums.insert(nums.end(), 10);                 // -1, 0..10
int arr[2] = {11,12};
nums.insert(nums.end(), arr, arr+2);         // 區間插入

8. 建構函數多樣化


list a(10, 0);              // 10 個 0
list b(a.begin(), a.end()); // 區間複製
vector v = {1,2};
list c(v.begin(), v.end()); // 從其他容器建構

9. 刪除操作全家族


list L = {0,1,2,3,4,5,6,7,8,9};
L.pop_front();           // 刪 0
L.pop_back();            // 刪 9
L.erase(L.begin());      // 刪 1
L.erase(L.begin(), L.end()); // 清空

L = {1,2,3,2,4};
L.remove(2);             // 刪除所有 2 → {1,3,4}

10. 通用演算法 remove (不改變容器大小)


L = {1,2,3,2,4};
auto newEnd = remove(L.begin(), L.end(), 2); // 邏輯移動: {1,3,4,2,4}
L.erase(newEnd, L.end());                    // 實際縮減: {1,3,4}

11. 進階:stable_partition + splice 命令列解析


list cmd = {"-w", "linux", "-o", "is", "great"};
auto isFlag = [](const string& s){ return s[0]=='-'; };
auto it = stable_partition(cmd.begin(), cmd.end(), isFlag);
// cmd: -w, -o, linux, is, great

list flags, files;
flags.splice(flags.end(), cmd, cmd.begin(), it); // 移動 flags
files.splice(files.end(), cmd);                  // 移動 files
// flags: -w, -o; files: linux, is, great

迭代器分類與容器對應

迭代器類別能力容器
Input單向讀istream
Output單向寫ostream, inserter
Forward單向讀寫forward_list
Bidirectional雙向讀寫list, set, map, multiset, multimap
RandomAccess隨機讀寫、算術vector, deque, array, string

實戰心得:商業專案驗證

  • 5000 行專案,處理 1-2 MB 報表,Linux GCC 2.7.2 → HP-UX,20 秒完成。
  • 大量使用 for_each, find, find_if, count, count_if。
  • 函數物件形成繼承樹,驅動控制流,程式碼模組化清晰。
  • STL 自動記憶體管理消除洩漏,邏輯錯誤大幅減少。

結語

透過 list 這個最簡單的序列容器,我們完整體驗了 STL「容器—演算法—迭代器」三位一體的設計哲學。掌握迭代器範圍 [first, last)、函數物件謂詞、成員函數與通用演算法的分工協作,即可舉一反三駕馭所有 STL 容器。關鍵在於理解迭代器類別決定演算法適用性 (如 sort 需 RandomAccess),並善用 splice、stable_partition 等進階組合解決實際問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved