STL标准library

LearningC++标准模板library using, includingcontainers, iterators, algorithmsetc.corecomponent

返回tutoriallist

1. STLoverview

1.1 what is STL

STL (Standard Template Library, 标准模板library) is C++标准library important 组成部分, 它providing了一套functions强 big 模板class and function, 用于processingcommon datastructure and algorithms. STL design目标 is providing reusable , high 效 , 泛型 component, 使C++程序员able to更 fast 速, 更 reliable 地Development程序.

STL 主要优势including:

  • code重用: STLproviding了 big 量ready-made component, 避免了重复Development.
  • High Efficiency: STL implementation经过精心optimization, performance通常优于手写code.
  • 泛型programming: through模板implementation, support不同dataclass型.
  • 标准化: serving asC++标准 一部分, ensured跨平台 consistency.

1.2 STL 组成部分

STL主要由以 under 几个部group成:

  • containers (Containers) : 用于storedata object, such asvector, list, mapetc..
  • iterators (Iterators) : 用于遍历containersin元素 object, class似于指针.
  • algorithms (Algorithms) : 用于operationcontainersin元素 function, such assort, find, copyetc..
  • functionobject (Functors) : behaviorclass似function object, 用于自定义algorithms behavior.
  • 适配器 (Adapters) : 用于modifycontainers, iterators or functionobjectinterface component.
  • 分配器 (Allocators) : 用于managementmemory分配 component.

1.3 STL 头file

usingSTL时, 需要package含相应 头file:

// containers相关头file
#include <vector>    // 向量
#include <list>      // 链表
#include <deque>     // 双端queue
#include <set>       // collection
#include <map>       // map
#include <unordered_set> // 无序collection (C++11) 
#include <unordered_map> // 无序map (C++11) 
#include <stack>     // 栈
#include <queue>     // queue

// algorithms相关头file
#include <algorithms> // commonalgorithms
#include <numeric>   // 数值algorithms

// iterators相关头file
#include <iterator>  // iterators适配器 and tool

// functionobject相关头file
#include <functional> // functionobject and 绑定器

2. containers

2.1 containersoverview

containers is STLin用于storedata object, 它们encapsulation了datastructure, 并providing了访问 and operationdata method. STLin containers可以分 for 以 under 几class:

  • 序列containers (Sequence Containers) : 按顺序store元素, such asvector, list, deque.
  • 关联containers (Associative Containers) : 按键值store元素, such asset, map.
  • 无序关联containers (Unordered Associative Containers) : 基于哈希表implementation, such asunordered_set, unordered_map (C++11) .
  • containers适配器 (Container Adapters) : modify现 has containers interface, such asstack, queue, priority_queue.

2.2 序列containers

2.2.1 vector

vector is 最常用 序列containers之一, 它 is a 动态array, 可以自动调整 big small . vector 元素store in 连续 memory空间in, support随机访问.

#include <iostream>
#include <vector>

using namespace std;

int main() {
    // creationvector
    vector<int> v1;             // 空vector
    vector<int> v2(5);           // package含5个默认初始化元素 vector
    vector<int> v3(5, 10);       // package含5个值 for 10 元素 vector
    vector<int> v4(v3);          // 拷贝construct
    vector<int> v5{1, 2, 3, 4, 5}; // list初始化 (C++11) 
    
    // 添加元素
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    
    // 访问元素
    cout << "v1[0] = " << v1[0] << endl;
    cout << "v1.at(1) = " << v1.at(1) << endl;
    cout << "v1.front() = " << v1.front() << endl;
    cout << "v1.back() = " << v1.back() << endl;
    
    // modify元素
    v1[2] = 10;
    
    // delete元素
    v1.pop_back();
    
    // 遍历元素
    cout << "遍历v1: ";
    for (int i = 0; i < v1.size(); i++) {
        cout << v1[i] << " ";
    }
    cout << endl;
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历v5: ";
    for (int x : v5) {
        cout << x << " ";
    }
    cout << endl;
    
    // other常用operation
    cout << "v5.size() = " << v5.size() << endl;
    cout << "v5.empty() = " << v5.empty() << endl;
    v5.clear();
    cout << "v5.size() after clear = " << v5.size() << endl;
    
    return 0;
}

2.2.2 list

list is a 双向链表, support in 任意位置 fast 速插入 and delete元素, 但不support随机访问.

#include <iostream>
#include <list>

using namespace std;

int main() {
    // creationlist
    list<int> l1;             // 空list
    list<int> l2(5);           // package含5个默认初始化元素 list
    list<int> l3(5, 10);       // package含5个值 for 10 元素 list
    list<int> l4(l3);          // 拷贝construct
    list<int> l5{1, 2, 3, 4, 5}; // list初始化 (C++11) 
    
    // 添加元素
    l1.push_back(1);  //  in 尾部添加
    l1.push_front(0); //  in 头部添加
    
    // 插入元素
    auto it = l1.begin();
    l1.insert(++it, 5); //  in 第二个位置插入5
    
    // 访问元素
    cout << "l1.front() = " << l1.front() << endl;
    cout << "l1.back() = " << l1.back() << endl;
    
    // delete元素
    l1.pop_back();   // delete尾部元素
    l1.pop_front();  // delete头部元素
    l1.erase(l1.begin()); // delete指定位置 元素
    
    // 遍历元素
    cout << "遍历l5: ";
    for (auto it = l5.begin(); it != l5.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历l5: ";
    for (int x : l5) {
        cout << x << " ";
    }
    cout << endl;
    
    // other常用operation
    cout << "l5.size() = " << l5.size() << endl;
    cout << "l5.empty() = " << l5.empty() << endl;
    l5.clear();
    cout << "l5.size() after clear = " << l5.size() << endl;
    
    // 链表特 has operation
    list<int> l6{3, 1, 4, 1, 5, 9};
    l6.sort(); // sort
    cout << "sort after : ";
    for (int x : l6) {
        cout << x << " ";
    }
    cout << endl;
    
    l6.unique(); // 去重
    cout << "去重 after : ";
    for (int x : l6) {
        cout << x << " ";
    }
    cout << endl;
    
    return 0;
}

2.2.3 deque

deque (双端queue) is asupport in 两端 fast 速插入 and delete元素 序列containers, 同时也support随机访问.

#include <iostream>
#include <deque>

using namespace std;

int main() {
    // creationdeque
    deque<int> d1;             // 空deque
    deque<int> d2(5);           // package含5个默认初始化元素 deque
    deque<int> d3(5, 10);       // package含5个值 for 10 元素 deque
    deque<int> d4(d3);          // 拷贝construct
    deque<int> d5{1, 2, 3, 4, 5}; // list初始化 (C++11) 
    
    // 添加元素
    d1.push_back(1);  //  in 尾部添加
    d1.push_front(0); //  in 头部添加
    
    // 访问元素
    cout << "d1[0] = " << d1[0] << endl;
    cout << "d1.at(1) = " << d1.at(1) << endl;
    cout << "d1.front() = " << d1.front() << endl;
    cout << "d1.back() = " << d1.back() << endl;
    
    // delete元素
    d1.pop_back();   // delete尾部元素
    d1.pop_front();  // delete头部元素
    
    // 遍历元素
    cout << "遍历d5: ";
    for (int i = 0; i < d5.size(); i++) {
        cout << d5[i] << " ";
    }
    cout << endl;
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历d5: ";
    for (int x : d5) {
        cout << x << " ";
    }
    cout << endl;
    
    // other常用operation
    cout << "d5.size() = " << d5.size() << endl;
    cout << "d5.empty() = " << d5.empty() << endl;
    d5.clear();
    cout << "d5.size() after clear = " << d5.size() << endl;
    
    return 0;
}

2.3 关联containers

2.3.1 set

set is a has 序collection, 它store唯一 元素, 并按照specific 顺序排列. setin 元素 is 不可modify .

#include <iostream>
#include <set>

using namespace std;

int main() {
    // creationset
    set<int> s1;             // 空set
    set<int> s2{5, 3, 1, 4, 2}; // list初始化 (C++11) 
    set<int> s3(s2);          // 拷贝construct
    
    // 添加元素
    s1.insert(1);
    s1.insert(2);
    s1.insert(3);
    s1.insert(2); // 重复元素, 不会被插入
    
    // find元素
    auto it = s1.find(2);
    if (it != s1.end()) {
        cout << "找 to 了元素: " << *it << endl;
    } else {
        cout << "元素未找 to " << endl;
    }
    
    // delete元素
    s1.erase(1); // through值delete
    s1.erase(s1.find(3)); // throughiteratorsdelete
    
    // 遍历元素
    cout << "遍历s2: ";
    for (auto it = s2.begin(); it != s2.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历s2: ";
    for (int x : s2) {
        cout << x << " ";
    }
    cout << endl;
    
    // other常用operation
    cout << "s2.size() = " << s2.size() << endl;
    cout << "s2.empty() = " << s2.empty() << endl;
    cout << "s2.count(3) = " << s2.count(3) << endl; // check元素 is 否存 in 
    s2.clear();
    cout << "s2.size() after clear = " << s2.size() << endl;
    
    return 0;
}

2.3.2 map

map is a has 序map, 它store键值 for , 其in键 is 唯一 , 并按照specific 顺序排列.

#include <iostream>
#include <map>
#include <string>

using namespace std;

int main() {
    // creationmap
    map<string, int> m1;             // 空map
    map<string, int> m2{{"Alice", 25}, {"Bob", 30}}; // list初始化 (C++11) 
    map<string, int> m3(m2);          // 拷贝construct
    
    // 添加元素
    m1["Alice"] = 25;
    m1["Bob"] = 30;
    m1.insert({"Charlie", 35}); // usinginsertmethod
    
    // find元素
    auto it = m1.find("Alice");
    if (it != m1.end()) {
        cout << "找 to 了元素: " << it->first << " => " << it->second << endl;
    } else {
        cout << "元素未找 to " << endl;
    }
    
    // 访问元素
    cout << "Alice 年龄: " << m1["Alice"] << endl;
    cout << "David 年龄: " << m1["David"] << endl; // 不存 in  键, 会插入默认值
    
    // delete元素
    m1.erase("Bob"); // through键delete
    m1.erase(m1.find("Charlie")); // throughiteratorsdelete
    
    // 遍历元素
    cout << "遍历m2: " << endl;
    for (auto it = m2.begin(); it != m2.end(); ++it) {
        cout << it->first << " => " << it->second << endl;
    }
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历m2: " << endl;
    for (auto& pair : m2) {
        cout << pair.first << " => " << pair.second << endl;
    }
    
    // other常用operation
    cout << "m2.size() = " << m2.size() << endl;
    cout << "m2.empty() = " << m2.empty() << endl;
    cout << "m2.count("Alice") = " << m2.count("Alice") << endl; // check键 is 否存 in 
    m2.clear();
    cout << "m2.size() after clear = " << m2.size() << endl;
    
    return 0;
}

2.4 无序关联containers

2.4.1 unordered_set

unordered_set is a 无序collection, 基于哈希表implementation, 它store唯一 元素, 插入 and findoperation 平均时间complexity for O(1).

#include <iostream>
#include <unordered_set>

using namespace std;

int main() {
    // creationunordered_set
    unordered_set<int> us1;             // 空unordered_set
    unordered_set<int> us2{5, 3, 1, 4, 2}; // list初始化 (C++11) 
    unordered_set<int> us3(us2);          // 拷贝construct
    
    // 添加元素
    us1.insert(1);
    us1.insert(2);
    us1.insert(3);
    us1.insert(2); // 重复元素, 不会被插入
    
    // find元素
    auto it = us1.find(2);
    if (it != us1.end()) {
        cout << "找 to 了元素: " << *it << endl;
    } else {
        cout << "元素未找 to " << endl;
    }
    
    // delete元素
    us1.erase(1); // through值delete
    us1.erase(us1.find(3)); // throughiteratorsdelete
    
    // 遍历元素
    cout << "遍历us2: ";
    for (auto it = us2.begin(); it != us2.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历us2: ";
    for (int x : us2) {
        cout << x << " ";
    }
    cout << endl;
    
    // other常用operation
    cout << "us2.size() = " << us2.size() << endl;
    cout << "us2.empty() = " << us2.empty() << endl;
    cout << "us2.count(3) = " << us2.count(3) << endl; // check元素 is 否存 in 
    us2.clear();
    cout << "us2.size() after clear = " << us2.size() << endl;
    
    return 0;
}

2.4.2 unordered_map

unordered_map is a 无序map, 基于哈希表implementation, 它store键值 for , 其in键 is 唯一 , 插入 and findoperation 平均时间complexity for O(1).

#include <iostream>
#include <unordered_map>
#include <string>

using namespace std;

int main() {
    // creationunordered_map
    unordered_map<string, int> um1;             // 空unordered_map
    unordered_map<string, int> um2{{"Alice", 25}, {"Bob", 30}}; // list初始化 (C++11) 
    unordered_map<string, int> um3(um2);          // 拷贝construct
    
    // 添加元素
    um1["Alice"] = 25;
    um1["Bob"] = 30;
    um1.insert({"Charlie", 35}); // usinginsertmethod
    
    // find元素
    auto it = um1.find("Alice");
    if (it != um1.end()) {
        cout << "找 to 了元素: " << it->first << " => " << it->second << endl;
    } else {
        cout << "元素未找 to " << endl;
    }
    
    // 访问元素
    cout << "Alice 年龄: " << um1["Alice"] << endl;
    cout << "David 年龄: " << um1["David"] << endl; // 不存 in  键, 会插入默认值
    
    // delete元素
    um1.erase("Bob"); // through键delete
    um1.erase(um1.find("Charlie")); // throughiteratorsdelete
    
    // 遍历元素
    cout << "遍历um2: " << endl;
    for (auto it = um2.begin(); it != um2.end(); ++it) {
        cout << it->first << " => " << it->second << endl;
    }
    
    // using范围for循环遍历 (C++11) 
    cout << "遍历um2: " << endl;
    for (auto& pair : um2) {
        cout << pair.first << " => " << pair.second << endl;
    }
    
    // other常用operation
    cout << "um2.size() = " << um2.size() << endl;
    cout << "um2.empty() = " << um2.empty() << endl;
    cout << "um2.count("Alice") = " << um2.count("Alice") << endl; // check键 is 否存 in 
    um2.clear();
    cout << "um2.size() after clear = " << um2.size() << endl;
    
    return 0;
}

2.5 containers适配器

2.5.1 stack

stack is a 栈适配器, 它providing了 after 进先出 (LIFO) operationinterface.

#include <iostream>
#include <stack>

using namespace std;

int main() {
    // creationstack
    stack<int> s;
    
    // 入栈
    s.push(1);
    s.push(2);
    s.push(3);
    
    // 访问栈顶元素
    cout << "栈顶元素: " << s.top() << endl;
    
    // 出栈
    s.pop();
    cout << "出栈 after 栈顶元素: " << s.top() << endl;
    
    // other常用operation
    cout << "栈  big  small : " << s.size() << endl;
    cout << "栈 is 否 for 空: " << s.empty() << endl;
    
    // 清空栈
    while (!s.empty()) {
        s.pop();
    }
    cout << "清空 after 栈 is 否 for 空: " << s.empty() << endl;
    
    return 0;
}

2.5.2 queue

queue is a queue适配器, 它providing了先进先出 (FIFO) operationinterface.

#include <iostream>
#include <queue>

using namespace std;

int main() {
    // creationqueue
    queue<int> q;
    
    // 入队
    q.push(1);
    q.push(2);
    q.push(3);
    
    // 访问队首 and 队尾元素
    cout << "队首元素: " << q.front() << endl;
    cout << "队尾元素: " << q.back() << endl;
    
    // 出队
    q.pop();
    cout << "出队 after 队首元素: " << q.front() << endl;
    
    // other常用operation
    cout << "queue  big  small : " << q.size() << endl;
    cout << "queue is 否 for 空: " << q.empty() << endl;
    
    // 清空queue
    while (!q.empty()) {
        q.pop();
    }
    cout << "清空 after queue is 否 for 空: " << q.empty() << endl;
    
    return 0;
}

3. iterators

3.1 iteratorsoverview

iterators is STLin用于遍历containersin元素 object, 它 behaviorclass似于指针. iteratorsproviding了一种统一 方式来访问不同containersin 元素, 使得algorithms可以独立于containers 具体implementation.

STLin iterators分 for 以 under 几class:

  • 输入iterators (Input Iterators) : 只读, 只能单向move.
  • 输出iterators (Output Iterators) : 只写, 只能单向move.
  • before 向iterators (Forward Iterators) : readable 写, 只能单向move.
  • 双向iterators (Bidirectional Iterators) : readable 写, 可以双向move.
  • 随机访问iterators (Random Access Iterators) : readable 写, 可以随机访问任意位置.

3.2 iterators using

#include <iostream>
#include <vector>
#include <list>

using namespace std;

int main() {
    // 向量 iterators (随机访问iterators) 
    vector<int> v{1, 2, 3, 4, 5};
    cout << "向量 iteratorsoperation: " << endl;
    
    // 遍历
    for (auto it = v.begin(); it != v.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // 随机访问
    auto it = v.begin();
    cout << "第一个元素: " << *it << endl;
    cout << "第三个元素: " << *(it + 2) << endl;
    cout << "最 after 一个元素: " << *(v.end() - 1) << endl;
    
    // 链表 iterators (双向iterators) 
    list<int> l{1, 2, 3, 4, 5};
    cout << "\n链表 iteratorsoperation: " << endl;
    
    // 遍历
    for (auto it = l.begin(); it != l.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // 双向move
    auto lit = l.begin();
    cout << "第一个元素: " << *lit << endl;
    ++lit;
    cout << "第二个元素: " << *lit << endl;
    --lit;
    cout << "回 to 第一个元素: " << *lit << endl;
    
    return 0;
}

3.3 iterators适配器

STLproviding了几种iterators适配器, 用于modifyiterators behavior:

  • 反向iterators (Reverse Iterators) : 用于反向遍历containers.
  • 插入iterators (Insert Iterators) : 用于 in containersin插入元素.
  • 流iterators (Stream Iterators) : 用于operation输入输出流.
#include <iostream>
#include <vector>
#include <iterator>

using namespace std;

int main() {
    // 反向iterators
    vector<int> v{1, 2, 3, 4, 5};
    cout << "反向遍历: " << endl;
    for (auto it = v.rbegin(); it != v.rend(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // 插入iterators
    vector<int> dest;
    dest.reserve(5); // 预分配空间
    
    // .back_inserter:  in containers尾部插入
    copy(v.begin(), v.end(), back_inserter(dest));
    cout << "usingback_inserter插入 after : " << endl;
    for (int x : dest) {
        cout << x << " ";
    }
    cout << endl;
    
    // 流iterators
    cout << "using流iterators输出: " << endl;
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
    
    return 0;
}

4. algorithms

4.1 algorithmsoverview

STLproviding了 big 量 algorithms, 用于operationcontainersin 元素. 这些algorithms定义 in <algorithms>头filein, 它们 big many 数 is 模板function, 可以用于不同class型 containers.

STLalgorithms classification:

  • findalgorithms: such asfind, binary_search, countetc..
  • sortalgorithms: such assort, stable_sort, partial_sortetc..
  • modifyalgorithms: such ascopy, fill, replaceetc..
  • 移除algorithms: such asremove, unique, eraseetc..
  • 排列algorithms: such asnext_permutation, prev_permutationetc..
  • 数值algorithms: such asaccumulate, inner_product, partial_sumetc. (定义 in <numeric>头filein) .

4.2 常用algorithmsexample

4.2.1 findalgorithms

#include <iostream>
#include <vector>
#include <algorithms>

using namespace std;

int main() {
    vector<int> v{1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
    
    // find: find元素
    auto it = find(v.begin(), v.end(), 5);
    if (it != v.end()) {
        cout << "找 to 了元素5, 位置: " << distance(v.begin(), it) << endl;
    } else {
        cout << "元素5未找 to " << endl;
    }
    
    // count: statistics元素出现次数
    int cnt = count(v.begin(), v.end(), 3);
    cout << "元素3出现 次数: " << cnt << endl;
    
    // count_if: statistics满足条件 元素个数
    int even_cnt = count_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; });
    cout << "偶数 个数: " << even_cnt << endl;
    
    // sort: sort
    sort(v.begin(), v.end());
    cout << "sort after : ";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;
    
    // binary_search: 二分find (需要先sort) 
    bool found = binary_search(v.begin(), v.end(), 5);
    cout << "二分find元素5: " << (found ? "找 to " : "未找 to ") << endl;
    
    return 0;
}

4.2.2 sort and modifyalgorithms

#include <iostream>
#include <vector>
#include <algorithms>

using namespace std;

int main() {
    vector<int> v{5, 2, 8, 1, 9, 3, 7, 4, 6};
    vector<int> dest(v.size());
    
    // sort
    sort(v.begin(), v.end());
    cout << "sort after : ";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;
    
    // 反转
    reverse(v.begin(), v.end());
    cout << "反转 after : ";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;
    
    // copy
    copy(v.begin(), v.end(), dest.begin());
    cout << "copy to dest: ";
    for (int x : dest) {
        cout << x << " ";
    }
    cout << endl;
    
    // 填充
    fill(dest.begin(), dest.begin() + 3, 0);
    cout << "填充 before 三个元素 for 0: ";
    for (int x : dest) {
        cout << x << " ";
    }
    cout << endl;
    
    // replace
    replace(v.begin(), v.end(), 5, 100);
    cout << "将5replace for 100: ";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;
    
    return 0;
}

4.2.3 数值algorithms

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

int main() {
    vector<int> v{1, 2, 3, 4, 5};
    
    // 累加
    int sum = accumulate(v.begin(), v.end(), 0);
    cout << "元素之 and : " << sum << endl;
    
    // 累乘
    int product = accumulate(v.begin(), v.end(), 1, multiplies<int>());
    cout << "元素之积: " << product << endl;
    
    // 计算相邻元素  and 
    vector<int> result(v.size());
    partial_sum(v.begin(), v.end(), result.begin());
    cout << "相邻元素  and : ";
    for (int x : result) {
        cout << x << " ";
    }
    cout << endl;
    
    // 计算相邻元素 差
    adjacent_difference(v.begin(), v.end(), result.begin());
    cout << "相邻元素 差: ";
    for (int x : result) {
        cout << x << " ";
    }
    cout << endl;
    
    return 0;
}

5. functionobject and lambda表达式

5.1 functionobject

functionobject (Functor) is abehaviorclass似于function object, 它 is a 重载了function调用运算符 (operator()) class instance. functionobject可以storestatus, 比普通function更加flexible.

#include <iostream>
#include <vector>
#include <algorithms>

using namespace std;

// functionobjectclass
class Square {
public:
    int operator()(int x) {
        return x * x;
    }
};

// 带status functionobject
class Counter {
private:
    int count;
public:
    Counter() : count(0) {}
    
    void operator()(int x) {
        if (x % 2 == 0) {
            count++;
        }
    }
    
    int getCount() const {
        return count;
    }
};

int main() {
    vector<int> v{1, 2, 3, 4, 5};
    
    // usingfunctionobject
    Square square;
    cout << "3 平方: " << square(3) << endl;
    
    //  in algorithmsinusingfunctionobject
    vector<int> squares(v.size());
    transform(v.begin(), v.end(), squares.begin(), square);
    cout << "每个元素 平方: ";
    for (int x : squares) {
        cout << x << " ";
    }
    cout << endl;
    
    // using带status functionobject
    Counter counter;
    counter = for_each(v.begin(), v.end(), counter);
    cout << "偶数 个数: " << counter.getCount() << endl;
    
    return 0;
}

5.2 Lambda表达式

Lambda表达式 (C++11) is acreation匿名functionobject 简便method, 它允许我们 in 需要function 地方直接定义function, 而不需要单独定义一个function or functionobjectclass.

#include <iostream>
#include <vector>
#include <algorithms>

using namespace std;

int main() {
    vector<int> v{5, 2, 8, 1, 9, 3, 7, 4, 6};
    
    // usinglambda表达式sort
    sort(v.begin(), v.end(), [](int a, int b) {
        return a < b;
    });
    cout << "sort after : ";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;
    
    // usinglambda表达式find
    auto it = find_if(v.begin(), v.end(), [](int x) {
        return x > 5;
    });
    if (it != v.end()) {
        cout << "第一个 big 于5 元素: " << *it << endl;
    }
    
    // usinglambda表达式modify元素
    transform(v.begin(), v.end(), v.begin(), [](int x) {
        return x * 2;
    });
    cout << "每个元素乘以2: ";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;
    
    // 带捕获 lambda表达式
    int threshold = 10;
    int count = 0;
    for_each(v.begin(), v.end(), [&count, threshold](int x) {
        if (x > threshold) {
            count++;
        }
    });
    cout << " big 于" << threshold << " 元素个数: " << count << endl;
    
    return 0;
}

实践case: 学生成绩managementsystem

usingSTLcontainers and algorithmsimplementation一个 simple 学生成绩managementsystem, including添加学生, query成绩, sort and statisticsetc.functions.

requirementsanalysis

  • store学生information (姓名, 学号, 成绩)
  • 添加学生information
  • 根据学号query学生information
  • 根据成绩sort
  • statistics平均分, 最 high 分 and 最 low 分
  • 按成绩etc.级groupstatistics

referencecode

#include <iostream>
#include <vector>
#include <algorithms>
#include <string>
#include <numeric>
#include <unordered_map>

using namespace std;

// 学生class
class Student {
public:
    string name;
    string id;
    double score;
    
    Student(string n, string i, double s) : name(n), id(i), score(s) {}
    
    void display() const {
        cout << "姓名: " << name << ", 学号: " << id << ", 成绩: " << score << endl;
    }
};

int main() {
    vector<Student> students;
    
    // 添加学生information
    students.emplace_back("Alice", "S1001", 95.5);
    students.emplace_back("Bob", "S1002", 85.5);
    students.emplace_back("Charlie", "S1003", 90.0);
    students.emplace_back("David", "S1004", 75.5);
    students.emplace_back("Eve", "S1005", 88.0);
    
    // 显示所 has 学生information
    cout << "所 has 学生information: " << endl;
    for (const auto& s : students) {
        s.display();
    }
    cout << endl;
    
    // 根据学号query学生
    string searchId = "S1003";
    auto it = find_if(students.begin(), students.end(), [&searchId](const Student& s) {
        return s.id == searchId;
    });
    if (it != students.end()) {
        cout << "query to 学号 for " << searchId << " 学生: " << endl;
        it->display();
    } else {
        cout << "未找 to 学号 for " << searchId << " 学生" << endl;
    }
    cout << endl;
    
    // 根据成绩sort ( from  high  to  low ) 
    sort(students.begin(), students.end(), [](const Student& s1, const Student& s2) {
        return s1.score > s2.score;
    });
    cout << "按成绩sort after : " << endl;
    for (const auto& s : students) {
        s.display();
    }
    cout << endl;
    
    // statistics平均分
    double sum = accumulate(students.begin(), students.end(), 0.0, [](double total, const Student& s) {
        return total + s.score;
    });
    double average = sum / students.size();
    cout << "平均分: " << average << endl;
    
    // statistics最 high 分 and 最 low 分
    auto maxIt = max_element(students.begin(), students.end(), [](const Student& s1, const Student& s2) {
        return s1.score < s2.score;
    });
    auto minIt = min_element(students.begin(), students.end(), [](const Student& s1, const Student& s2) {
        return s1.score < s2.score;
    });
    cout << "最 high 分: " << maxIt->score << " (" << maxIt->name << ") " << endl;
    cout << "最 low 分: " << minIt->score << " (" << minIt->name << ") " << endl;
    cout << endl;
    
    // 按成绩etc.级groupstatistics
    unordered_map<string, int> gradeCount;
    for (const auto& s : students) {
        string grade;
        if (s.score >= 90) {
            grade = "A";
        } else if (s.score >= 80) {
            grade = "B";
        } else if (s.score >= 70) {
            grade = "C";
        } else if (s.score >= 60) {
            grade = "D";
        } else {
            grade = "F";
        }
        gradeCount[grade]++;
    }
    cout << "按成绩etc.级groupstatistics: " << endl;
    for (const auto& pair : gradeCount) {
        cout << "etc.级" << pair.first << ": " << pair.second << "人" << endl;
    }
    
    return 0;
}

互动练习

练习1: usingvectorstore一组整数, 然 after implementation以 under functions:

  • 添加元素
  • delete元素
  • find元素
  • sort元素
  • 计算元素 and , 平均值, 最 big 值 and 最 small 值

练习2: usingmapstore学生 姓名 and 成绩, 然 after implementation以 under functions:

  • 添加学生information
  • modify学生成绩
  • delete学生information
  • find学生成绩
  • 按姓名sort输出
  • statistics成绩 in 90分以 on 学生人数

练习3: usingSTLalgorithmsimplementation以 under functions:

  • usingtransform将vectorin 每个元素转换 for 其平方
  • usingcopy_if将vectorin 偶数copy to 另一个vectorin
  • usingreplace将vectorin 所 has 0replace for 100
  • usingsort and lambda表达式按string long 度sortvector<string>
  • usingaccumulate计算vectorin所 has 元素 乘积