当前位置:   article > 正文

【C++】——【 STL简介】——【详细讲解】

【C++】——【 STL简介】——【详细讲解】

目录

​编辑

1. 什么是STL

2. STL的版本

3. STL的六大组件

1.容器(Container):

2.算法(Algorithm):

3.迭代器(Iterator):

4.函数(Function):

5.适配器(Adapter):

6.分配器(Allocator):

4. STL的重要性

5. 如何学习STL

6. STL的缺陷

总结


专栏:C++学习笔记 

1. 什么是STL

STL(Standard Template Library,标准模板库)是C++标准库的重要组成部分。它不仅是一个可复用的组件库,而且是一个包含数据结构与算法的软件框架。STL为开发者提供了多种高效、灵活且可扩展的模板化工具,使得复杂的程序开发变得更加简单和高效。

代码示例:使用STL的vector容器

  1. #include <iostream>
  2. #include <vector>
  3. int main() {
  4. std::vector<int> numbers = {1, 2, 3, 4, 5};
  5. for (int num : numbers) {
  6. std::cout << num << " ";
  7. }
  8. std::cout << std::endl;
  9. return 0;
  10. }

运行结果

小李很执着理解

  • vector就像一个可以自动扩展的数组,你可以随意添加或删除元素。
  • 在上面的例子中,创建了一个包含数字1到5的vector,并输出这些数字。

2. STL的版本

STL经历了多个版本的发展,不同版本有不同的特点和应用场景:

  • 原始版本:由Alexander Stepanov和Meng Lee在惠普实验室完成的原始版本。这个版本是开源的,允许任何人任意使用、修改和传播。
  • P. J. 版本:由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用。这一版本不能公开或修改,其缺陷在于可读性较低,符号命名比较怪异。
  • RW版本:由Rouge Wage公司开发,继承自HP版本,被C++ Builder采用,也不能公开或修改,但可读性一般。
  • SGI版本:由Silicon Graphics Computer Systems公司开发,继承自HP版本,被GCC(Linux)采用。这个版本可移植性好,可公开、修改甚至商业使用。从命名风格和编程风格上看,阅读性非常高。

小李很执着理解

  • 不同版本的STL是由不同的人和公司开发的,有些版本是开源的,有些版本是商业化的。
  • 学习STL时主要参考SGI版本,因为它的可读性和移植性都很好。

3. STL的六大组件

STL由以下六大组件组成:

1.容器(Container)

用于存储和组织数据的对象,如vectorlistdequesetmap等。

代码示例:使用map容器

  1. #include <iostream>
  2. #include <map>
  3. int main() {
  4. std::map<std::string, int> age;
  5. age["Alice"] = 30;
  6. age["Bob"] = 25;
  7. for (const auto& pair : age) {
  8. std::cout << pair.first << " is " << pair.second << " years old." << std::endl;
  9. }
  10. return 0;
  11. }

 运行结果

小李很执着理解

map就像一本字典,可以根据“键”(如名字)查找对应的“值”(如年龄)。

在上面的例子中,创建了一个名字和年龄的对应关系,并打印出来。

2.算法(Algorithm)

用于操作容器中的数据的函数集合,如排序、查找、复制、删除等。

代码示例:使用sort算法

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. int main() {
  5. std::vector<int> numbers = {4, 2, 5, 1, 3};
  6. std::sort(numbers.begin(), numbers.end());
  7. for (int num : numbers) {
  8. std::cout << num << " ";
  9. }
  10. std::cout << std::endl;
  11. return 0;
  12. }

 运行结果

小李很执着理解

sort算法可以对容器中的元素进行排序。

在上面的例子中,对一个包含随机数字的vector进行了排序,并打印出了排序后的结果。

3.迭代器(Iterator)

用于在容器中遍历元素的对象,类似于指针。常见的有forward_iteratorbidirectional_iteratorrandom_access_iterator等。

代码示例:使用iterator遍历vector

  1. #include <iostream>
  2. #include <vector>
  3. int main() {
  4. std::vector<int> numbers = {1, 2, 3, 4, 5};
  5. std::vector<int>::iterator it;
  6. for (it = numbers.begin(); it != numbers.end(); ++it) {
  7. std::cout << *it << " ";
  8. }
  9. std::cout << std::endl;
  10. return 0;
  11. }

 运行结果

小李很执着理解

iterator类似于指针,可以用来遍历容器中的元素。

在上面的例子中,使用iterator遍历了一个vector,并打印出了每个元素。

4.函数(Function)

STL提供了一些函数对象和仿函数,用于实现自定义的算法行为。

代码示例:使用greater仿函数

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <functional>
  5. int main() {
  6. std::vector<int> numbers = {4, 2, 5, 1, 3};
  7. std::sort(numbers.begin(), numbers.end(), std::greater<int>());
  8. for (int num : numbers) {
  9. std::cout << num << " ";
  10. }
  11. std::cout << std::endl;
  12. return 0;
  13. }

 运行结果

小李很执着理解

greater是一个仿函数,用来实现降序排序。

在上面的例子中,使用greater仿函数对vector进行了降序排序,并打印出了排序后的结果。

5.适配器(Adapter)

用于修改容器或仿函数行为的组件,如stackqueuepriority_queue等。

代码示例:使用stack适配器

  1. #include <iostream>
  2. #include <stack>
  3. int main() {
  4. std::stack<int> s;
  5. s.push(1);
  6. s.push(2);
  7. s.push(3);
  8. while (!s.empty()) {
  9. std::cout << s.top() << " ";
  10. s.pop();
  11. }
  12. std::cout << std::endl;
  13. return 0;
  14. }

 运行结果

小李很执着理解

stack是一种先进后出(LIFO)的数据结构,就像叠盘子,最后放的盘子最先拿出来。

在上面的例子中,往stack中添加了三个数字,并按顺序取出了这些数字。

6.分配器(Allocator)

用于管理内存分配和释放的组件。

代码示例:自定义分配器

  1. #include <iostream>
  2. #include <memory>
  3. #include <vector>
  4. template<typename T>
  5. struct SimpleAllocator {
  6. typedef T value_type;
  7. SimpleAllocator() = default;
  8. template<typename U>
  9. SimpleAllocator(const SimpleAllocator<U>&) {}
  10. T* allocate(std::size_t n) {
  11. return static_cast<T*>(::operator new(n * sizeof(T)));
  12. }
  13. void deallocate(T* p, std::size_t) noexcept {
  14. ::operator delete(p);
  15. }
  16. };
  17. int main() {
  18. std::vector<int, SimpleAllocator<int>> vec = {1, 2, 3, 4, 5};
  19. for (int num : vec) {
  20. std::cout << num << " ";
  21. }
  22. std::cout << std::endl;
  23. return 0;
  24. }

 运行结果

小李很执着理解

分配器负责管理内存的分配和释放,可以自定义来满足特定需求。

在上面的例子中,实现了一个简单的分配器,并用它来创建一个vector,然后打印出了vector中的元素。

知识点:STL的六大组件各有用途,组合使用可以解决复杂的数据处理问题。

4. STL的重要性

STL在C++开发中占有重要地位,其重要性主要体现在以下几个方面:

在笔试中:STL提供的高效算法和容器常常在编程题中使用,如二叉树层序打印、重建二叉树、用两个栈实现一个队列等。

代码示例:用两个栈实现一个队列

  1. #include <iostream>
  2. #include <stack>
  3. class Queue {
  4. private:
  5. std::stack<int> stack1, stack2;
  6. public:
  7. void enqueue(int x) {
  8. stack1.push(x);
  9. }
  10. int dequeue() {
  11. if (stack2.empty()) {
  12. while (!stack1.empty()) {
  13. stack2.push(stack1.top());
  14. stack1.pop();
  15. }
  16. }
  17. if (stack2.empty()) {
  18. throw std::out_of_range("Queue is empty");
  19. }
  20. int top = stack2.top();
  21. stack2.pop();
  22. return top;
  23. }
  24. };
  25. int main() {
  26. Queue q;
  27. q.enqueue(1);
  28. q.enqueue(2);
  29. q.enqueue(3);
  30. std::cout << q.dequeue() << " "; // 输出1
  31. std::cout << q.dequeue() << " "; // 输出2
  32. std::cout << q.dequeue() << std::endl; // 输出3
  33. return 0;
  34. }

 运行结果

小李很执着理解

通过使用两个栈,可以实现一个队列的功能,先进先出(FIFO)。

在上面的例子中,创建了一个队列,往其中添加了三个数字,并按顺序取出了这些数字。

在面试中:掌握STL是衡量C++开发者能力的重要标准之一。面试官常常通过STL相关问题考察候选人的算法能力和代码实现能力。

在工作中:STL使得开发者无需重复实现基础数据结构和算法,可以专注于业务逻辑的实现,大幅提升开发效率和代码质量。

网上有句话说:“不懂STL,不要说你会C++”。这句话充分体现了STL在C++开发中的重要性。

5. 如何学习STL

学习STL可以分为三个阶段:能用、明理、能扩展。

能用:首先要掌握STL的基本用法,了解各类容器、算法和迭代器的使用方法,并能够在实际开发中应用。

代码示例:使用vectorsort

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. int main() {
  5. std::vector<int> numbers = {4, 2, 5, 1, 3};
  6. std::sort(numbers.begin(), numbers.end());
  7. for (int num : numbers) {
  8. std::cout << num << " ";
  9. }
  10. std::cout << std::endl;
  11. return 0;
  12. }

 运行结果

小李很执着理解

学习STL的第一步是能够正确使用它的各种容器和算法。

在上面的例子中,使用了vectorsort,并打印了排序后的结果。

明理:深入理解STL的内部实现原理,了解各组件的设计思想和工作机制,掌握常见问题的解决方法。

知识点:例如,了解vector如何管理动态数组的内存,如何在内部实现扩容等。

能扩展:在掌握基础知识的基础上,能够根据具体需求对STL进行扩展或优化,如自定义分配器、实现特定算法等。

代码示例:自定义分配器

  1. #include <iostream>
  2. #include <memory>
  3. #include <vector>
  4. template<typename T>
  5. struct SimpleAllocator {
  6. typedef T value_type;
  7. SimpleAllocator() = default;
  8. template<typename U>
  9. SimpleAllocator(const SimpleAllocator<U>&) {}
  10. T* allocate(std::size_t n) {
  11. return static_cast<T*>(::operator new(n * sizeof(T)));
  12. }
  13. void deallocate(T* p, std::size_t) noexcept {
  14. ::operator delete(p);
  15. }
  16. };
  17. int main() {
  18. std::vector<int, SimpleAllocator<int>> vec = {1, 2, 3, 4, 5};
  19. for (int num : vec) {
  20. std::cout << num << " ";
  21. }
  22. std::cout << std::endl;
  23. return 0;
  24. }

 运行结果

小李很执着理解

学习STL的高级阶段是能够根据需求进行扩展,比如自定义分配器。

在上面的例子中,实现了一个简单的分配器,并用它来创建一个vector

知识点学习STL不仅要会用,还要理解其原理,进而能够根据需求进行扩展。

6. STL的缺陷

虽然STL功能强大,但也存在一些缺陷:

更新速度慢STL库的更新速度较慢。自C++98之后,中间的C++03版本仅做了一些修订,直到C++11才有进一步的更新。

缺乏线程安全:STL目前不支持线程安全。在并发环境下,开发者需要自己加锁,而且锁的粒度较大。

内部复杂:STL极度追求效率,导致内部实现比较复杂,如类型萃取、迭代器萃取等机制。

代码膨胀问题:由于模板语法的特性,STL的使用会导致代码膨胀,例如使用vector<vector<vector<int>>>这样的嵌套容器会生成多份代码。

小李很执着理解

STL虽然强大,但也有一些问题,比如更新慢、不支持线程安全、内部复杂和代码膨胀。

了解这些缺陷可以帮助在使用过程中规避潜在的问题,并根据需求做出合理的取舍和优化。

总结

总结来说,STL是C++开发中不可或缺的重要工具。掌握STL不仅能够大幅提升开发效率和代码质量,还能帮助开发者更深入地理解C++语言的精髓。在学习和使用STL的过程中,虽然会遇到一些挑战和问题,但其带来的便利和效率提升是无可替代的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/900318
推荐阅读
相关标签
  

闽ICP备14008679号