容器管理記憶體與存取介面,演算法實作邏輯,迭代器串聯兩者 — 這是泛型程式設計 (GP) 精髓。
#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
if (milkshakes.empty()) { /* ... */ }
cout << "大小: " << milkshakes.size() << '\n';
// 手動
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());
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());
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());
list staff = {"John", "Bill", "Tony", "Fidel", "Nelson"};
staff.sort(); // 成員函數,merge sort,穩定
// 結果: Bill, Fidel, John, Nelson, Tony
原因:std::sort 需隨機存取迭代器,list 只提供雙向迭代器,故需專用 sort()。
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); // 區間插入
list a(10, 0); // 10 個 0
list b(a.begin(), a.end()); // 區間複製
vector v = {1,2};
list c(v.begin(), v.end()); // 從其他容器建構
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}
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}
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 |
for_each, find, find_if, count, count_if。透過 list 這個最簡單的序列容器,我們完整體驗了 STL「容器—演算法—迭代器」三位一體的設計哲學。掌握迭代器範圍 [first, last)、函數物件謂詞、成員函數與通用演算法的分工協作,即可舉一反三駕馭所有 STL 容器。關鍵在於理解迭代器類別決定演算法適用性 (如 sort 需 RandomAccess),並善用 splice、stable_partition 等進階組合解決實際問題。