详细介绍C++ STL编程(深入解析C++ STL编程实战指南)
原创
一、C++ STL简介
STL(Standard Template Library,标准模板库)是C++标准库的一部分,它提供了一系列模板化的数据结构和算法,用于处理数据集合。STL首要包括容器(Containers)、迭代器(Iterators)、算法(Algorithms)和函数对象(Function Objects)四个部分。
二、STL容器
STL容器是用于存储数据集合的对象,首要包括序列容器和相关性容器两大类。
1. 序列容器
序列容器包括vector、deque、list、forward_list和array。以下分别介绍这些容器的特点:
vector
vector是一个动态数组,赞成随机访问,其内存是连续分配的。vector在尾部添加或删除元素时非常高效,但在中间插入或删除元素时高效能较低,由于需要移动后续元素。
#include
#include
int main() {
std::vector
v = {1, 2, 3, 4, 5}; for (int i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
}
std::cout << std::endl;
return 0;
}
deque
deque(双端队列)是一种赞成在两端迅速插入和删除的容器。deque内部由一段连续的内存和一个中央控制结构组成,可以在两端迅速插入或删除元素。
#include
#include
int main() {
std::deque
d = {1, 2, 3, 4, 5}; for (auto it = d.begin(); it != d.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
list
list是一个双向链表,赞成双向遍历,插入和删除操作都非常高效。但list不赞成随机访问,访问特定位置的元素需要从头或尾遍历。
#include
#include
int main() {
std::list
l = {1, 2, 3, 4, 5}; for (auto it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
forward_list
forward_list是一个单向链表,只赞成单向遍历。与list相比,forward_list在内存使用和性能上都有一定优势,但功能较为简洁。
#include
#include
int main() {
std::forward_list
fl = {1, 2, 3, 4, 5}; for (auto it = fl.begin(); it != fl.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
array
array是一个固定大小的数组,其内存是连续分配的。与vector相比,array在创建时需要指定大小,且大小不可改变。
#include
#include
int main() {
std::array
a = {1, 2, 3, 4, 5}; for (int i = 0; i < a.size(); ++i) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
return 0;
}
2. 相关性容器
相关性容器包括set、multiset、map、multimap、unordered_set、unordered_multiset、unordered_map和unordered_multimap。以下分别介绍这些容器的特点:
set
set是一个有序集合,内部使用红黑树实现,元素自动排序,且元素值唯一。
#include
#include
int main() {
std::set
s = {5, 2, 3, 1, 4}; for (auto it = s.begin(); it != s.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
multiset
multiset与set类似,但允许存储相同值的多个元素。
#include
#include
int main() {
std::multiset
ms = {5, 2, 3, 1, 4, 3}; for (auto it = ms.begin(); it != ms.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
map
map是一个有序映射,内部使用红黑树实现,每个元素包含一个键和一个值,键是唯一的,值可以相同。
#include
#include
int main() {
std::map
m = {{1, "one"}, {2, "two"}, {3, "three"}}; for (auto it = m.begin(); it != m.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
multimap
multimap与map类似,但允许存储具有相同键的多个元素。
#include
#include
int main() {
std::multimap
mm = {{1, "one"}, {2, "two"}, {3, "three"}, {3, "three2"}}; for (auto it = mm.begin(); it != mm.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
unordered_set
unordered_set是一个无序集合,内部使用哈希表实现,元素值唯一,不自动排序。
#include
#include
int main() {
std::unordered_set
us = {5, 2, 3, 1, 4}; for (auto it = us.begin(); it != us.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
unordered_multiset
unordered_multiset与unordered_set类似,但允许存储相同值的多个元素。
#include
#include
int main() {
std::unordered_multiset
ums = {5, 2, 3, 1, 4, 3}; for (auto it = ums.begin(); it != ums.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
unordered_map
unordered_map是一个无序映射,内部使用哈希表实现,每个元素包含一个键和一个值,键是唯一的,值可以相同。
#include
#include
int main() {
std::unordered_map
um = {{1, "one"}, {2, "two"}, {3, "three"}}; for (auto it = um.begin(); it != um.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
unordered_multimap
unordered_multimap与unordered_map类似,但允许存储具有相同键的多个元素。
#include
#include
int main() {
std::unordered_multimap
umm = {{1, "one"}, {2, "two"}, {3, "three"}, {3, "three2"}}; for (auto it = umm.begin(); it != umm.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
三、STL迭代器
迭代器是一种抽象指针,用于遍历容器中的元素。STL迭代器分为输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器五种类型。
1. 输入迭代器
输入迭代器只能用于读取元素,不能修改元素。例如,std::vector
2. 输出迭代器
输出迭代器只能用于写入元素,不能读取元素。例如,std::back_insert_iterator是输出迭代器。
3. 前向迭代器
前向迭代器可以读取和修改元素,但只能单向遍历。例如,std::list
4. 双向迭代器
双向迭代器可以读取和修改元素,且可以双向遍历。例如,std::deque
5. 随机访问迭代器
随机访问迭代器可以读取和修改元素,且可以随机访问任意位置的元素。例如,std::vector
四、STL算法
STL算法是用于处理数据集合的一系列模板函数,包括排序、查找、替换、合并、分区、排列组合等。
1. 排序算法
排序算法包括std::sort、std::stable_sort、std::partial_sort等。以下是一个使用std::sort的示例:
#include
#include
#include
int main() {
std::vector
v = {5, 2, 3, 1, 4}; std::sort(v.begin(), v.end());
for (int i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
}
std::cout << std::endl;
return 0;
}
2. 查找算法
查找算法包括std::find、std::find_if、std::find_end等。以下是一个使用std::find的示例:
#include
#include
#include
int main() {
std::vector
v = {5, 2, 3, 1, 4}; auto it = std::find(v.begin(), v.end(), 3);
if (it != v.end()) {
std::cout << "Found: " << *it << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
return 0;
}
3. 替换算法
替换算法包括std::replace、std::replace_if等。以下是一个使用std::replace的示例:
#include
#include
#include
int main() {
std::vector
v = {5, 2, 3, 1, 4}; std::replace(v.begin(), v.end(), 2, 8);
for (int i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
}
std::cout << std::endl;
return 0;
}
4. 合并算法
合并算法包括std::merge、std::inplace_merge等。以下是一个使用std::merge的示例:
#include
#include
#include
int main() {
std::vector
v1 = {1, 3, 5}; std::vector
v2 = {2, 4, 6}; std::vector
v3; v3.reserve(v1.size() + v2.size());
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3));
for (int i = 0; i < v3.size(); ++i) {
std::cout << v3[i] << " ";
}
std::cout << std::endl;
return 0;
}
五、函数对象
函数对象是一种行为类似于函数的对象,它可以存储状态,并可以被调用。在STL中,函数对象通常用于算法中的比较、替换等操作。
1. 函数对象的使用
以下是一个使用函数对象的示例,该示例使用std::sort和一个自定义的比较函数对象来对整数数组进行降序排序:
#include
#include
#include
// 自定义比较函数对象
struct Descending {
bool operator()(int a, int b) const {
return a > b;
}
};
int main() {
std::vector
v = {5, 2, 3, 1, 4}; std::sort(v.begin(), v.end(), Descending());
for (int i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
}
std::cout << std::endl;
return 0;
}
2. 函数对象的适配器
STL提供了函数对象的适配器,用于创建新的函数对象。例如,std::negate是一个函数对象适配器,它可以创建一个取反的函数对象。
#include
#include
#include
int main() {
std::vector
v = {5, 2, 3, 1, 4}; std::transform(v.begin(), v.end(), v.begin(), std::negate
()); for (int i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
}
std::cout << std::endl;
return 0;
}
六、总结
C++ STL是C++编程中非常有力的工具,它提供了充裕的数据结构和算法,让处理数据集合变得更加简洁和高效。通过深入明白STL的原理和使用方法,可以大大尽或许降低损耗编程高效能,编写出更加优雅和高效的代码。