当前位置:首页 » 《我的小黑屋》 » 正文

C++ STL 学习指南:带你快速掌握标准模板库

15 人参与  2024年11月05日 08:01  分类 : 《我的小黑屋》  评论

点击全文阅读


?快来参与讨论?,点赞?、收藏⭐、分享?,共创活力社区。 ?

 

大家好呀!? 今天我们来聊一聊 C++ 程序员的必备神器——STL(Standard Template Library,标准模板库)。如果你是 C++ 初学者或者还没深入了解过 STL 的朋友,这篇文章将带你快速入门,揭开 STL 的神秘面纱!?

 你是否觉得自己在 C++ 中经常需要实现一些重复的代码,比如排序、查找数据、动态数组扩容等等? 如果你也有这样的烦恼,那么 STL 可以完美解决这些问题!它能够极大地简化我们的代码,减少不必要的工作量,同时提高开发效率。?


目录

什么是 STL??

一、容器(Containers):你的数据储物箱 ?

1. vector:动态数组 ?

vector的实战案例 ?

2. list:双向链表 ?

list的妙用

3. map:键值对存储 ?️

使用 map 进行数据统计

4. unordered_map:哈希表 ?

5. stack 和 queue:方便的数据处理 ?

二、算法(Algorithms):高效的代码助推器 ?️

1. 排序与查找:sort 和 find ?

2. 统计与累加:count 和 accumulate ?

3. 自定义操作:for_each 函数 ✨

三、迭代器(Iterators):容器与算法的桥梁 ?

迭代器的种类

迭代器的实际应用 ?

四、总结:STL 的使用技巧 ?


什么是 STL??

STL 是 C++ 的标准库之一,包含了一系列 模板类函数模板,主要用于提供通用的数据结构和算法。简单来说,STL 就是帮你解决“重复造轮子”的问题,让你更专注于实现逻辑,而不是耗费时间在基础数据结构的实现上。

STL 包含了三个核心组件:

容器(Containers) ?:用于存储数据的集合,比如 vectorlistmap 等。算法(Algorithms) ?️:常用算法的集合,比如排序、查找、遍历等。迭代器(Iterators) ?:连接容器与算法的“桥梁”,用于遍历容器内的元素。

接下来,我们将依次了解这些组件,看看 STL 是如何让编程变得更轻松的!?


一、容器(Containers):你的数据储物箱 ?

容器是 STL 的核心部分,提供了多种数据存储结构。每种容器都有各自的特点和适用场景,以下是一些常见的容器:

1. vector:动态数组 ?

vector 是一种动态数组,可以根据需要自动扩展容量。它的特点是 支持随机访问,并且在末尾添加和删除元素的效率很高。

vector的实战案例 ?
#include <iostream>#include <vector>int main() {    std::vector<int> vec = {1, 2, 3};    vec.push_back(4);  // 在末尾添加元素    vec.push_back(5);    vec[1] = 10;       // 修改第二个元素    for (int num : vec) {        std::cout << num << " ";    }    return 0;}

 

适用场景:当你需要频繁读取某个位置的元素时,vector 是首选!✨

注意事项vector 的扩容是成倍增长的,因此它有时会多分配一些内存来应对未来的增长。如果能提前知道数据量的大小,最好使用 reserve() 减少扩容带来的性能开销。

2. list:双向链表 ?

list 是双向链表,适合在任意位置进行插入和删除操作。与 vector 不同的是,它不支持随机访问,因此访问某个特定位置的元素效率较低。

list的妙用
#include <list>#include <iostream>int main() {    std::list<int> lst = {1, 2, 3};    lst.push_front(0);  // 在开头添加元素    lst.push_back(4);   // 在末尾添加元素    lst.insert(++lst.begin(), 100);  // 在第二个位置插入 100    for (int num : lst) {        std::cout << num << " ";    }    return 0;}

 

适用场景:如果你的程序需要频繁插入和删除元素,而对随机访问的需求不高,list 会是更好的选择!?

实际体验:在某些情况下,使用list 进行插入操作的代码比 vector 更加简洁和高效,尤其是在需要频繁的插入和删除操作时。

3. map:键值对存储 ?️

map 是一种关联容器,基于红黑树实现,可以用来存储键值对(key-value)。map 自动对键进行排序,并且不允许键重复。

使用 map 进行数据统计
#include <map>#include <iostream>int main() {    std::map<std::string, int> ages;    ages["Alice"] = 25;    ages["Bob"] = 30;    ages["Charlie"] = 22;    // 输出所有人的年龄    for (const auto& pair : ages) {        std::cout << pair.first << ": " << pair.second << "\n";    }    return 0;}

适用场景:当你需要根据键快速查找对应值时,map 是一个非常方便的选择!✨

个人经验分享:如果你的程序需要频繁修改数据,可以选择 unordered_map,它的查找效率更高,但不保证有序性。

4. unordered_map:哈希表 ?

unordered_map 类似于 map,但是它使用哈希表实现,因此查找速度在平均情况下更快。它不保证元素的顺序。

使用unordered_map 的小窍门unordered_map 使用的是哈希函数,因此如果你的键是自定义类型,请记得实现适当的哈希函数,否则可能会出现编译错误。

5. stackqueue:方便的数据处理 ?

stack queue 是两种特殊的容器适配器,分别实现了 后进先出(LIFO)和 先进先出(FIFO)的数据处理模式。

示例代码:

#include <stack>#include <queue>#include <iostream>int main() {    std::stack<int> stk;    stk.push(1);    stk.push(2);    stk.push(3);    while (!stk.empty()) {        std::cout << stk.top() << " ";        stk.pop();    }    std::queue<int> que;    que.push(1);    que.push(2);    que.push(3);    while (!que.empty()) {        std::cout << que.front() << " ";        que.pop();    }    return 0;}

适用场景stack 适用于需要处理递归或回退逻辑的场景,而 queue 适用于按顺序处理数据的情况,例如任务排队。 


二、算法(Algorithms):高效的代码助推器 ?️

STL 的算法库提供了丰富的工具,使得编程变得更加简单。你可以使用这些算法来处理容器中的数据,而不用重复编写类似的逻辑代码。

1. 排序与查找:sortfind ?

sort():可以轻松对容器进行排序。find():在容器中查找指定元素。

 示例代码:

#include <vector>#include <algorithm>#include <iostream>int main() {    std::vector<int> vec = {5, 2, 9, 1, 5, 6};    std::sort(vec.begin(), vec.end()); // 排序    auto it = std::find(vec.begin(), vec.end(), 9); // 查找    if (it != vec.end()) {        std::cout << "Found: " << *it << "\n";    } else {        std::cout << "Not found\n";    }    return 0;}

 

亲身体验:使用 STL 的算法库,可以让你把更多精力放在业务逻辑上,而不是实现底层算法,这就是 STL 的魅力所在。?

2. 统计与累加:countaccumulate ?

count():统计某个元素在容器中出现的次数。accumulate():累加容器中的元素。
#include <vector>#include <numeric> // 包含 accumulate#include <algorithm>#include <iostream>int main() {    std::vector<int> vec = {1, 2, 3, 4, 3, 2, 3};    int count3 = std::count(vec.begin(), vec.end(), 3); // 统计3的数量    int sum = std::accumulate(vec.begin(), vec.end(), 0); // 求和    std::cout << "Number of 3s: " << count3 << "\n";    std::cout << "Sum: " << sum << "\n";    return 0;}

3. 自定义操作:for_each 函数 ✨

for_each 函数可以帮助你对容器中的每个元素进行自定义操作,比如打印每个元素、改变它们的值等等。

#include <vector>#include <algorithm>#include <iostream>int main() {    std::vector<int> vec = {1, 2, 3, 4, 5};    std::for_each(vec.begin(), vec.end(), [](int& num) {        num *= 2; // 将每个元素乘以2        std::cout << num << " ";    });    return 0;}v

 应用场景:如果你有特定的逻辑想要应用到容器中的每个元素,for_each 非常好用,可以用 Lambda 表达式让代码更加简洁。

 


三、迭代器(Iterators):容器与算法的桥梁 ?

迭代器是 STL 的精髓,它让你可以方便地遍历容器中的元素,同时与 STL 的算法进行无缝配合。

迭代器的种类

输入迭代器(Input Iterator):只读。输出迭代器(Output Iterator):只写。前向迭代器(Forward Iterator):可读写,可向前遍历。双向迭代器(Bidirectional Iterator):可向前和向后遍历。随机访问迭代器(Random Access Iterator):支持随机访问,类似指针。

迭代器的实际应用 ?

#include <vector>#include <iostream>int main() {    std::vector<int> vec = {1, 2, 3, 4, 5};    // 使用正向迭代器    for (auto it = vec.begin(); it != vec.end(); ++it) {        std::cout << *it << " ";    }    std::cout << "\n";    // 使用反向迭代器    for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {        std::cout << *rit << " ";    }    return 0;}

 经验分享:通过熟练掌握迭代器,你可以实现对各种容器的灵活操作,使代码更加优雅、简洁。迭代器甚至可以用来实现自定义算法,非常强大!?

 


四、总结:STL 的使用技巧 ?

在日常开发中,合理使用 STL 可以大幅提升代码的效率和简洁性。以下是一些 STL 使用的小技巧:

选择合适的容器:根据需求选择合适的容器,比如频繁访问使用 vector,频繁插入删除使用 list,键值对查找使用 map使用算法库:STL 中的算法库包含了常用的排序、查找、计算等函数,避免重复造轮子!掌握迭代器:迭代器是 STL 的精髓,熟练掌握迭代器可以使你的代码更灵活、更高效。预分配容量:对于 vector,如果可以预知数据量,使用 reserve() 预分配容量可以减少扩容带来的性能损耗。注意迭代器失效:某些操作(如在 vector 中插入或删除元素)会导致迭代器失效,务必小心处理。

希望通过这篇文章,大家对 C++ 的 STL 有了一个初步了解!? STL 是 C++ 中非常强大的一部分,如果你能熟练使用 STL,将会让你的编程效率提升一大步!?

别忘了给文章点个赞?,让更多人了解 STL 的魅力吧!如有问题,欢迎在评论区交流讨论!?

 欢迎关注我?【A Charmer】


点击全文阅读


本文链接:http://zhangshiyu.com/post/182543.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1