C++之STL入门
STL
- STL引言
- 一、STL的三大核心组件
- (一)容器(Containers)
- (二)迭代器(Iterators)
- (三)算法(Algorithms)
- 二、STL的优势
- (一)高效性
- (二)通用性
- (三)安全性
- 三.C++范围for以及auto
- (一)范围for循环
- 支持范围 for 的类型
- 示例
- (二)`auto`关键字
- 示例
- 修改容器中的元素
- (三)总结

STL引言
C++标准模板库(Standard Template Library,简称STL)是C++语言中一个极其重要的组成部分,它为C++程序员提供了一系列高效、灵活且功能强大的数据结构和算法。STL的出现极大地简化了C++编程,让我们能够更加专注于解决问题的核心逻辑,而不是底层数据结构的实现细节。
一、STL的三大核心组件
STL主要由三大核心组件构成:容器(Containers)、迭代器(Iterators)和算法(Algorithms)。这三者相互协作,构成了STL的强大功能体系。
(一)容器(Containers)
容器是STL中用于存储数据的结构,它提供了多种不同类型的容器来满足不同的存储需求。常见的容器包括:
- 序列容器:
std::vector
:动态数组,支持快速随机访问,但在尾部插入和删除元素时效率较高。例如,std::vector<int> vec; vec.push_back(10);
可以快速地在动态数组尾部添加元素。std::list
:双向链表,适合频繁插入和删除元素,但不支持随机访问。例如,std::list<int> lst; lst.push_front(5);
可以在链表头部快速插入元素。std::deque
:双端队列,支持在两端快速插入和删除元素,同时也能进行随机访问。例如,std::deque<int> dq; dq.push_back(20); dq.push_front(10);
可以在双端队列的两端进行操作。
- 关联容器:
std::set
:基于红黑树的有序集合,自动对元素进行排序,且元素唯一。例如,std::set<int> s; s.insert(10);
插入的元素会自动排序并去重。std::map
:基于红黑树的有序映射,键值对唯一,自动按键排序。例如,std::map<int, std::string> m; m[1] = "one";
可以快速地通过键访问对应的值。std::unordered_set
和std::unordered_map
:基于哈希表的无序集合和映射,提供更快的查找速度,但不保证元素的顺序。
(二)迭代器(Iterators)
迭代器是STL中用于遍历容器的工具,它类似于指针,但提供了更通用的接口。迭代器使得我们可以用统一的方式遍历不同类型的容器。例如:
std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";
}
迭代器有多种类型,包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器,每种迭代器提供了不同级别的操作能力。
(三)算法(Algorithms)
STL提供了大量通用算法,这些算法可以应用于任何满足特定要求的容器。常见的算法包括:
- 排序算法:
std::sort
:对容器中的元素进行排序。例如,std::sort(vec.begin(), vec.end());
可以对std::vector
中的元素进行升序排序。std::stable_sort
:稳定排序算法,保持相等元素的相对顺序。
- 查找算法:
std::find
:在容器中查找特定元素。例如,auto it = std::find(vec.begin(), vec.end(), 3);
可以查找值为3的元素。std::binary_search
:在有序容器中进行二分查找。
- 变换算法:
std::transform
:对容器中的元素进行变换操作。例如,std::transform(vec.begin(), vec.end(), vec.begin(), [](int x) { return x * x; });
可以将容器中的每个元素平方。
二、STL的优势
(一)高效性
STL的容器和算法都是经过精心设计和优化的,能够提供高效的性能。例如,std::vector
在内存连续存储方面表现出色,std::set
和std::map
基于红黑树的实现保证了对数级的查找和插入效率。
(二)通用性
STL的算法和容器通过模板机制实现了高度的通用性。这意味着我们可以用相同的算法对不同类型的数据进行操作,大大减少了代码的重复性。
(三)安全性
STL提供了丰富的边界检查和错误处理机制,能够有效避免一些常见的编程错误,如数组越界等。
三.C++范围for以及auto
在C++中,范围for循环(range-based for loop)和auto
关键字是C++11标准引入的两个非常有用的特性,它们可以提高代码的可读性和简洁性。
(一)范围for循环
范围for循环是一种更简洁的遍历容器(如数组、向量、列表等)的方式,其基本语法如下:
for (范围声明 : 表达式) {// 循环体
}
- 范围声明:用于声明一个变量,该变量在每次迭代中都会被赋予表达式中的下一个元素的值。
- 表达式:通常是一个容器,如数组、
std::vector
、std::list
等。
支持范围 for 的类型
范围 for 循环可以用于:
数组
所有 STL 容器(vector, list, map 等)
初始化列表
任何定义了begin()和end()成员函数或自由函数的类型
示例
假设有一个std::vector<int>
,我们想遍历它并打印每个元素:
#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};for (int i : vec) {std::cout << i << " ";}return 0;
}
输出:
1 2 3 4 5
(二)auto
关键字
auto
关键字用于自动推导变量的类型。在C++11之前,我们通常需要显式地声明变量的类型,这在某些情况下可能会很繁琐,尤其是当类型非常复杂时。auto
可以让编译器自动推导出变量的实际类型。
示例
#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 使用auto自动推导类型for (auto i : vec) {std::cout << i << " ";}return 0;
}
输出:
1 2 3 4 5
在这个例子中,auto
自动推导出i
的类型为int
。
修改容器中的元素
如果你想在范围for循环中修改容器中的元素,可以使用引用。例如:
#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 使用引用修改容器中的元素for (auto& i : vec) {i *= 2;}for (int i : vec) {std::cout << i << " ";}return 0;
}
输出:
2 4 6 8 10
(三)总结
- 范围for循环:提供了一种简洁的方式来遍历容器,使代码更加易读。
auto
关键字:自动推导变量类型,减少显式类型声明的繁琐,尤其在处理复杂类型时非常有用。