C++ STL(Standard Template Library,标准模板库)
一、C++ STL(Standard Template Library,标准模板库)简介
- 什么是STL
- STL是一个具有工业强度的、高效的C++库,它抽象了数据结构和算法,提供了一套通用的工具,用于处理数据集合和容器。
- STL的设计借鉴了函数式编程语言中的“容器”和“算法”的概念,数据将结构(容器)与操作数据的算法分离,从而提高了代码的复用性和可读性。
- STL的主要组成部分
- 容器(Containers):用于存储和组织数据,例如`vector`(动态数组)、`list`(双向链表)、`map`(关联容器,键值对存储)等。
- 算法(Algorithms):用于对容器中的数据进行操作,例如`sort`(排序)、`find`(查找)、`copy`(复制)等。
- 迭代器(Iterators):类似于指针,用于访问容器中的元素,为算法操作容器中的数据提供了通用接口。
- 函数对象(Function Objects):也称为仿函数,是通过重载`operator()`使其能够被像函数一样调用的对象,用于自定义算法的行为。
- 配接器(Adaptors):用于扩展容器的功能或改变算法的行为,例如`stack`(栈适配器)和`queue`(队列适配器)。
二、STL容器
1. 序列容器
- `std::vector`
- 特点:动态数组,可以动态扩展和收缩。
- 使用方式:
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec[0] = 10; // 通过下标访问
- 适用场景:适用于需要随机访问元素且对连续内存存储有要求的场景。
- `std::list`
- 特点:双向链表,支持在任意位置快速插入和删除元素。
- 使用方式:
std::list<int> lst;
lst.push_back(1);
lst.push_front(2);
lst.erase(lst.begin()); // 删除第一个元素
- 适用场景:适用于频繁插入和删除元素的场景。
- `std::deque`(双端队列)
- 特点:支持从头部和尾部快速插入和删除元素。
- 使用方式:
std::deque<int> dq;
dq.push_front(1);
dq.push_back(2);
dq.pop_front(); // 删除头部元素
- 适用场景:适用于需要从两端操作数据的场景,如双端队列。
2. 关联容器
- `std::set`
- 特点:自动排序且不存储重复元素。
- 使用方式:
stdset::<int> s;
s.insert(1);
s.insert(2);
s.erase(1); // 删除元素
- 适用场景:适用于需要去重和有序存储的场景。
- `std::map`
- 特点:键值对存储,按键自动排序。
- 使用方式:
std::map<std::string, int> m;
m["apple"] =1 ;
m["banana"] = 2;
for (auto& pair : m) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
- 适用场景:适用于需要通过键值快速查找和存储的场景。
3. 容器适配器
- `std::stack`(栈)
- 特点:后进先出的数据结构。
- 使用方式:
std::stack<int> stk;
stk.push(1);
stk.push(2);
stk.pop(); // 删除栈顶元素
- `std::queue`(队列)
- 特点:先进先出的数据结构。
- 使用方式:
std::queue<int> q;
q.push(1);
q.push(2);
q.pop(); // 删除队列头部元素
- `std::priority_queue`(优先队列)
- 特点:元素按照优先级排序,优先级最高的元素最先出队。
- 使用方式:
std::priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.pop(); // 删除优先级最高的元素
三、STL算法
- 通用算法
- `std::sort`(排序)
- 功能:对容器中的元素进行排序。
- 使用方式:
std::vector<int> vec = {3, 1, 2};
std::sort(vec.begin(), vec.end()); // 升序排序
- `std::find`(查找)
- 功能:在容器中查找指定元素。
- 使用方式:
std::vector<int> vec = {1, 2, 3};
auto it = std::find(vec.begin(), vec.end(), 2);
if (it != vec.end()) {
std::cout << "Found!" << std::endl;
}
- `std::copy`(复制)
- 功能:将容器中的元素复制到另一个容器。
- 使用方式:
std::vector<int> vec = {1, 2, 3};
std::vector<int> vec2(vec.size());
std::copy(vec.begin(), vec.end(), vec2.begin());
算法分类
- 非修改算法:不修改容器中的元素,如`find`、`count`等。
- 修改算法:会修改容器中的元素,如`sort`、`replace`等。
四、STL迭代器
- 迭代器分类
- 随机访问迭代器:支持所有迭代器操作,效率最高,例如`vector`的迭代器。
- 双向迭代器:支持前后移动,例如`list`的迭代器。
- 输入迭代器:只能单向移动,用于读取数据。
- 输出迭代器:只能单向移动,用于写入数据。
- 迭代器使用示例
- 遍历容器:
std::vector<int> vec = {1, 2, 3};
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << std::endl;
}
五、STL的优点
- 高度封装:STL将数据结构和算法封装为模板,用户无需从头实现,减少了开发工作量。
- 高效性:STL的实现经过优化,性能表现良好。
- 可扩展性:支持自定义数据结构和算法,能够满足多样化的开发需求。
- 通用性:通过模板机制,STL可以适应各种不同类型的元素。
六、STL的缺点
- 复杂性:STL的语法和概念较为复杂,初学者可能会感到难以理解。
- 性能开销:虽然STL本身高效,但在某些特定场景下(如对内存严格要求的嵌入式系统),可能会带来额外的性能开销(如动态内存分配)。
- 调试困难:由于STL的抽象程度较高,某些情况下出错时难以定位问题。
总的来说,STL是C++程序员不可或缺的工具之一,它极大地提升了C++的表达能力和开发效率。然而,合理使用STL,根据实际需求选择合适的容器和算法,才是发挥其优势的关键。