C++标准模板库STL介绍

  • STL的六大组成部分

STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,提供了丰富的通用数据结构和算法,使得 C++ 编程变得更加高效和方便。STL 包括了 6 大类组件,分别是算法(Algorithm)、容器(Container)、空间分配器(Allocator)、迭代器(Iterator)、函数对象(Functor)、适配器(Adapter),下面对每个组件进行详细介绍:

  1. 算法(Algorithm):
    STL 中的算法包括了大量的通用算法,如排序、查找、遍历等,可以对容器中的元素进行各种操作和处理。常见的算法包括 sort、find、for_each 等。

  2. 容器(Container):
    STL 提供了多种容器类,用于存储和管理数据。常见的容器包括 vector、list、deque、set、map 等,每种容器都有自己独特的特性和适用场景。

  3. 空间分配器(Allocator):
    STL 中的空间分配器用于管理内存分配和释放,可以自定义空间分配策略,为容器提供灵活的内存管理能力。

  4. 迭代器(Iterator):
    迭代器是 STL 中用于遍历容器元素的通用接口,提供了统一的遍历方式,使得算法和容器之间的解耦更加灵活和高效。

  5. 函数对象(Functor):
    函数对象是可调用对象,即可以像函数一样被调用。STL 中的函数对象可以作为算法的参数,用于自定义比较、操作等功能。

  6. 适配器(Adapter):
    适配器用于调整容器或迭代器的接口,使得它们能够适配不同的需求。常见的适配器包括 stack、queue、priority_queue 等。

通过合理使用 STL 中的各种组件,可以极大地提高 C++ 编程的效率和质量,减少重复劳动并提升代码的可维护性。熟练掌握 STL 的使用方法对于 C++ 程序员来说是非常重要的。

  • 算法案例

STL(Standard Template Library)中的算法模块提供了丰富的通用算法,包括排序、查找、复制、转换等等,用于对容器中的元素进行各种操作和处理。这些算法能够极大地提高 C++ 编程的效率和灵活性。下面我将详细介绍几种常用的算法,并结合代码实例展示它们的用法:

1. 排序算法(sort):

  • std::sort 算法用于对容器中的元素进行排序,默认是按升序排列。
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {5, 2, 8, 1, 6};std::sort(vec.begin(), vec.end());for (int num : vec) {std::cout << num << " ";}return 0;
}

2. 查找算法(find):

  • std::find 算法用于在容器中查找指定元素,并返回第一个匹配元素的迭代器。
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {5, 2, 8, 1, 6};auto it = std::find(vec.begin(), vec.end(), 8);if (it != vec.end()) {std::cout << "Element found at position: " << std::distance(vec.begin(), it) << std::endl;} else {std::cout << "Element not found" << std::endl;}return 0;
}

3. 复制算法(copy):

  • std::copy 算法用于将一个容器中的元素复制到另一个容器中。
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> source = {5, 2, 8, 1, 6};std::vector<int> dest(source.size());std::copy(source.begin(), source.end(), dest.begin());for (int num : dest) {std::cout << num << " ";}return 0;
}

4. 转换算法(transform):

  • std::transform 算法用于对容器中的元素进行转换操作,可以根据指定的操作函数将元素转换为另一种形式。
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {5, 2, 8, 1, 6};std::vector<int> result(vec.size());std::transform(vec.begin(), vec.end(), result.begin(), [](int n) { return n * 2; });for (int num : result) {std::cout << num << " ";}return 0;
}

以上代码示例演示了 STL 中几种常用算法的用法,包括排序、查找、复制和转换等。这些算法能够极大地提高 C++ 编程的效率,使得对容器中元素的操作更加方便和灵活。开发者可以根据具体需求灵活运用这些算法,提高代码的可读性和可维护性。

  • STL常见容器与用法

下面是关于 STL 中常见容器(vector、list、deque、set、map)的代码实例,展示了它们的基本用法和操作:

1. vector(向量):

  • vector 是一个动态数组,支持随机访问和动态增删元素。
#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};vec.push_back(6); // 在末尾添加元素vec.pop_back();   // 删除末尾元素for (int num : vec) {std::cout << num << " ";}return 0;
}

2. list(链表):

  • list 是一个双向链表,支持快速插入和删除操作。
#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3, 4, 5};myList.push_front(0); // 在头部插入元素myList.pop_back();    // 删除尾部元素for (int num : myList) {std::cout << num << " ";}return 0;
}

3. deque(双端队列):

  • deque 是一个双端队列,支持在两端进行快速插入和删除操作。
#include <iostream>
#include <deque>int main() {std::deque<int> myDeque = {1, 2, 3, 4, 5};myDeque.push_front(0); // 在头部插入元素myDeque.pop_back();    // 删除尾部元素for (int num : myDeque) {std::cout << num << " ";}return 0;
}

4. set(集合):

  • set 是一个有序且不重复的集合,支持快速查找和插入操作。
#include <iostream>
#include <set>int main() {std::set<int> mySet = {5, 2, 7, 3, 1};mySet.insert(6); // 插入元素mySet.erase(2);  // 删除元素for (int num : mySet) {std::cout << num << " ";}return 0;
}

5. map(映射):

  • map 是一个键值对映射的容器,支持根据键快速查找对应的值。
#include <iostream>
#include <map>int main() {std::map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 7}};myMap["pear"] = 4;  // 插入键值对myMap.erase("banana"); // 删除键值对for (auto& pair : myMap) {std::cout << pair.first << ": " << pair.second << std::endl;}return 0;
}

以上代码示例展示了 STL 中常见容器(vector、list、deque、set、map)的基本用法和操作。这些容器在不同场景下有着各自的特点和适用性,可以根据需求选择合适的容器来存储和管理数据,提高代码的效率和可维护性。

  • STL的空间分配器

STL 的空间分配器(Allocator)是用于管理内存分配和释放的机制,它在 STL 容器和算法中起着重要的作用。空间分配器的主要原理是将内存分配和释放的操作抽象出来,使得容器可以独立于具体的内存管理方式。空间分配器的设计可以使得容器更加灵活,可以针对不同的需求选择不同的内存管理策略。

空间分配器的主要功能包括两个方面:

  1. 内存分配(allocation):在需要动态分配内存时,空间分配器负责向系统请求合适大小的内存块,并返回给容器或算法使用。
  2. 内存释放(deallocation):在不再需要使用内存时,空间分配器负责将内存块返回给系统,以便系统可以重新利用这些内存空间。

空间分配器的设计可以根据具体需求进行优化,比如可以实现自定义的内存池管理策略,提高内存分配的效率,避免频繁的系统调用。

下面是一个简单的示例代码,展示了如何使用 STL 的空间分配器进行内存分配和释放操作:

#include <iostream>
#include <vector>
#include <memory> // 包含了 STL 的默认空间分配器int main() {// 使用 STL 的默认空间分配器进行内存分配std::allocator<int> alloc;// 在堆上分配存储 5 个 int 类型的内存空间int* ptr = alloc.allocate(5);// 初始化分配的内存空间for (int i = 0; i < 5; ++i) {alloc.construct(ptr + i, i+1);}// 打印分配的内存空间中的值for (int i = 0; i < 5; ++i) {std::cout << ptr[i] << " ";}std::cout << std::endl;// 释放内存空间for (int i = 0; i < 5; ++i) {alloc.destroy(ptr + i);}alloc.deallocate(ptr, 5);return 0;
}

在STL的空间分配器中,constructdestroy是用来构造和销毁对象的方法,它们与内存的分配和释放息息相关。

  1. construct方法
    • construct 方法用于在已分配的内存空间中构造对象。当我们通过空间分配器分配了一块内存空间后,如果需要在这块内存上构造对象(例如调用对象的构造函数),就可以使用construct方法。
    • construct方法的用法是:alloc.construct(pointer, args...),其中alloc是空间分配器对象,pointer是指向要构造对象的内存地址的指针,args...是传递给对象构造函数的参数。
  2. destroy方法
    • destroy 方法用于销毁对象,即调用对象的析构函数并释放对象占用的资源。在释放由空间分配器分配的内存之前,需要先销毁内存中的对象,避免内存泄漏。
    • destroy方法的用法是:alloc.destroy(pointer),其中alloc是空间分配器对象,pointer是指向要销毁的对象的指针。

这两个方法通常与allocate(分配内存)和deallocate(释放内存)方法配合使用,确保在分配的内存空间上正确构造对象并在释放内存之前销毁。

  • STL迭代器

STL(Standard Template Library)中的迭代器(Iterator)是用来遍历和操作容器中元素的工具,是一种抽象化的概念,提供了统一的访问接口,使得算法可以独立于容器进行操作。STL 中有多种迭代器种类,每种迭代器都有不同的特点和适用场景。下面我将详细介绍几种常见的迭代器种类,并通过代码演示它们的使用:

1. 输入迭代器(Input Iterator):

  • 输入迭代器用于从容器中读取元素,但只能单向移动,不支持写操作。
#include <iostream>
#include <vector>
#include <iterator>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};std::vector<int>::iterator it = vec.begin();std::istream_iterator<int> input_it(std::cin);// 通过输入迭代器遍历容器并输出元素while (it != vec.end() && input_it != std::istream_iterator<int>()) {std::cout << *it << " ";++it;++input_it;}return 0;
}

2. 输出迭代器(Output Iterator):

  • 输出迭代器用于向容器中写入元素,但只能单向移动,不支持读操作。
#include <iostream>
#include <vector>
#include <iterator>int main() {std::vector<int> vec;std::ostream_iterator<int> output_it(std::cout, " ");// 通过输出迭代器向容器中写入元素for (int i = 1; i <= 5; ++i) {*output_it = i;}return 0;
}

3. 前向迭代器(Forward Iterator):

  • 前向迭代器支持单向遍历和修改容器内容,可以多次遍历容器中的元素。
#include <iostream>
#include <forward_list>int main() {std::forward_list<int> myList = {1, 2, 3, 4, 5};for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}return 0;
}

4. 双向迭代器(Bidirectional Iterator):

  • 双向迭代器支持双向遍历和修改容器内容,可以向前或向后移动迭代器。
#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3, 4, 5};for (auto it = myList.rbegin(); it != myList.rend(); ++it) {std::cout << *it << " ";}return 0;
}

以上代码示例演示了几种常见的迭代器种类(输入迭代器、输出迭代器、前向迭代器、双向迭代器)的使用方法。不同种类的迭代器具有不同的功能和特点,开发者可以根据具体需求选择合适的迭代器来遍历和操作容器中的元素,提高代码的灵活性和可维护性。

  • 函数对象

函数对象(Functor)是一种重载了函数调用运算符 () 的类对象,可以像函数一样被调用。函数对象可以在 STL 算法中作为参数传递,用于自定义排序、查找、转换等操作。下面详细介绍几种函数对象的定义和用法:

1. 函数对象类:

  • 最常见的函数对象是重载了 operator() 的类对象。通过定义一个类并重载 operator(),可以实现自定义的函数功能。
#include <iostream>// 函数对象类
class AddFunctor {
public:int operator()(int a, int b) {return a + b;}
};int main() {AddFunctor add;std::cout << add(3, 5) << std::endl; // 调用函数对象return 0;
}

2. Lambda 表达式:

  • Lambda 表达式是一种匿名函数,可以方便地定义并使用函数对象,通常用于简单的函数功能。
#include <iostream>int main() {auto add = [](int a, int b) { return a + b; };std::cout << add(3, 5) << std::endl; // 调用 Lambda 表达式return 0;
}

3. 标准函数对象:

  • STL 提供了一些内置的函数对象,如 std::plusstd::minusstd::greater 等,用于实现常见的函数功能。
#include <iostream>
#include <functional>int main() {std::plus<int> add;std::cout << add(3, 5) << std::endl; // 使用标准函数对象return 0;
}

4. 适配器函数对象:

  • 适配器函数对象用于修改或适配其他函数对象的行为,如 std::not1std::bind1st 等。
#include <iostream>
#include <functional>int main() {std::not1<std::greater<int>> not_greater;std::cout << not_greater(3, 5) << std::endl; // 适配器函数对象return 0;
}

通过以上几种方式定义函数对象,我们可以实现不同的功能和行为,并在 STL 算法中灵活应用。函数对象提供了一种将数据和操作捆绑在一起的方式,使得代码更加清晰和模块化。在实际开发中,根据具体需求选择合适的函数对象定义方式,可以提高代码的可读性和灵活性。

  • 适配器

STL(Standard Template Library)提供了多种适配器(Adapter),用于修改或扩展容器、迭代器和函数对象的行为,以满足不同的需求。适配器是一种设计模式,可以在不改变原有组件接口的情况下,增加新的功能或修改原有功能。下面详细介绍几种常见的 STL 适配器及其用法:

1. 迭代器适配器:

  • 迭代器适配器用于修改迭代器的行为或范围,包括插入迭代器、反向迭代器、流迭代器等。
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 插入迭代器,用于在容器中插入元素std::back_insert_iterator<std::vector<int>> back_it(vec);*back_it = 6;// 反向迭代器,用于逆序遍历容器std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));return 0;
}

2. 容器适配器:

  • 容器适配器用于修改容器的行为或接口,包括栈(stack)、队列(queue)、优先队列(priority_queue)等。
#include <iostream>
#include <stack>int main() {std::stack<int> myStack;myStack.push(1);myStack.push(2);myStack.push(3);while (!myStack.empty()) {std::cout << myStack.top() << " ";myStack.pop();}return 0;
}

3. 函数适配器:

  • 函数适配器用于修改函数对象的行为或参数,包括绑定器(binder)、否定器(negator)等。
#include <iostream>
#include <functional>int main() {std::multiplies<int> mult;std::cout << mult(3, 4) << std::endl; // 乘法函数对象std::negate<int> neg;std::cout << neg(5) << std::endl; // 取反函数对象return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/33106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

# Kafka_深入探秘者(3):kafka 消费者

Kafka_深入探秘者&#xff08;3&#xff09;&#xff1a;kafka 消费者 一、kafka 消费者、消费组 1、Kafka 消费者是消费组的一部分&#xff0c;当多个消费者形成一个消费组来消费主题时&#xff0c;每个消费者会收到不同分区的消息。假设有一个 T1 主题&#xff0c;该主题有…

Web应用防火墙(WAF)(上:基础概念篇)

运维专题 Web应用防火墙&#xff08;WAF&#xff09;&#xff08;上&#xff1a;基础概念篇&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. She…

pgAdmin后台命令执行漏洞(CVE-2023-5002)

​ 我们可以看到针对于漏洞 CVE-2022-4223&#xff0c;官方做了一定的修复措施。 web\pgadmin\misc_init_.py#validate_binary_path ​ 首先是添加了 login_required​ 进行权限校验。在 Flask 框架中&#xff0c;login_required​ 装饰器通常与 Flask-Login 扩展一起使用。…

LED恒流调光电路

LED等在工作的时候发热较大&#xff0c;所以通常选用铝基板作为底板&#xff1b;常用白色油墨。 LED必须在恒流源电路下工作&#xff0c;下图为最简单的恒流源&#xff1a;B极电压3.3V不变左下侧蓝色的为稳压二极管&#xff0c;由于BE极可以看做二极管&#xff0c;压降为0.7V&…

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统&#xff0c;而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备&#xff0c;并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线…

OpenCV颜色检测

OpenCV颜色检测 前言策略分析根据颜色检测目标对象相关链接 前言 绿幕技术是一种经典的视频编辑技术&#xff0c;可以用于将人物置于不同的背景中。例如在电影制作中&#xff0c;技术的关键在于演员不能身着特定颜色的衣服(比如绿色)&#xff0c;站在只有绿色的背景前。然后&a…

异地组网如何OEM?

在现代信息社会中&#xff0c;企业越来越需要跨地域进行数据传输与共享。面临的挑战却是如何在不暴露在公网的情况下&#xff0c;实现异地组网并保障数据的安全性。本文将介绍一种名为“异地组网OEM”的解决方案&#xff0c;该方案能够通过私有通道传输数据并对数据进行安全加密…

大数据平台之Flink

Apache Flink是一款开源的流处理框架&#xff0c;用于处理实时数据流和批处理数据。它由Apache Software Foundation开发和维护&#xff0c;提供了丰富的功能和特性&#xff0c;适用于各种复杂的数据处理任务。下面是对Flink的详细介绍&#xff1a; 1. 基本概念 流处理&#…

我的大学生活-人面不知何处去(大三篇)

我的大学生活&#xff08;大三篇&#xff09; 前言推荐大三&#xff08;人面不知何处去&#xff09;2022年8月2022年9月2022年10月2022年11月2022年12月 寒假2023年1月 大三&#xff08;人面不知何处去&#xff09;2023年2月2023年3月2023年4月2023年5月2023年6月 暑假2023年7月…

(十三)、MQTT3.1.1-MQTT服务端数据结构设计

为进一步实现一个简易的MQTT服务端&#xff0c;做如下服务端数据结构设计。 1、服务端协议相关的函数 连接 rx_connect() 接收连接请求 Socket中监听&#xff0c;通过第一个字节switch&#xff0c;根据数据创建client对象 tx_connectack() 回复连接响应 处理完成rx_conn…

【LeedCode】二分查找算法(一)

二分查找算法的时间复杂度是O(logN) &#xff0c;更优于传统的遍历数组算法值得我们学习。 注意二分查找一般使用的前提是&#xff1a;待操作的数组的元素有某种规律也就是要有二阶性&#xff0c;二段性就是在数组中选取一点根据该数组元素某种规律可以把数组分为两部分&#x…

国企:2024年6月中国移动相关招聘信息 三

中国移动卓望公司-卓望信息 卓望公司成立于2000年6月,是中国移动的控股子公司,积极拓展互联网、IT、ICT领域,提供平台及应用开发、运营运维等服务。  成立二十余年来,卓望公司逐渐形成包括业务合作管理、内容渠道运营、网络集中运维、企业服务、安全服务、行业DICT服务等…

笔记-python的with用法

一、With语句是什么&#xff1f; 在编程中&#xff0c;有些任务需要在执行前进行设置&#xff0c;并在完成后进行清理。针对这种情况&#xff0c;Python的with语句提供了一种非常方便的处理方式。一个典型的例子是文件处理&#xff1a;需要打开一个文件句柄&#xff0c;从中读…

LDR6500U,让设备爱上“被骗”的充电速度!

在数字设备日新月异的今天&#xff0c;兼容性和充电效率已成为用户关注的核心焦点。尤其是随着电子设备市场的全球化发展&#xff0c;标准化的需求日益凸显。近期&#xff0c;欧洲联盟&#xff08;简称“欧盟”&#xff09;就电子设备充电接口问题做出了重要决策&#xff0c;要…

高校新生如何选择最优手机流量卡?

一年一度的高考已经结束了&#xff0c;愿广大学子金榜题名&#xff0c;家长们都给孩子准备好了手机&#xff0c;那么手机流量卡应该如何选择呢&#xff1f; 高校新生在选择手机流量卡时&#xff0c;需要综合考量流量套餐、费用、网络覆盖、售后服务等多方面因素&#xff0c;以下…

办理河南建筑工程乙级设计资质的流程与要点

办理河南建筑工程乙级设计资质的流程与要点 办理河南建筑工程乙级设计资质的流程与要点主要包括以下几个方面&#xff1a; 流程&#xff1a; 工商注册与资质规划&#xff1a;确保企业具有独立法人资格&#xff0c;完成工商注册&#xff0c;并明确乙级设计资质的具体要求&…

Java开发-实际工作经验和技巧-0001-PostgreSQL数据库存储磁盘满了重启以及应急措施

Java开发-实际工作经验和技巧-0001-PostgreSQL数据库存储磁盘满了重启以及应急措施 更多内容欢迎关注我&#xff08;持续更新中&#xff0c;欢迎Star✨&#xff09; Github&#xff1a;CodeZeng1998/Java-Developer-Work-Note 技术公众号&#xff1a;CodeZeng1998&#xff0…

【Unity Shader】片段着色器(Fragment Shader)的概念及其使用方法

在Unity和图形编程中&#xff0c;片段着色器&#xff08;Fragment Shader&#xff09;是渲染管线中的一个阶段&#xff0c;负责计算屏幕上每个像素&#xff08;片段&#xff09;的颜色和特性。片段着色器通常在顶点着色器和任何几何处理之后运行&#xff0c;是决定最终像素颜色…

用于射频功率应用的氮化铝电阻元件

EAK推出了新的厚膜氮化铝 &#xff08;AlN&#xff09; 电阻器和端接系列&#xff0c;以补充公司现有的产品。传统上&#xff0c;射频功率电阻元件采用氧化铍&#xff08;BeO&#xff09;陶瓷材料作为陶瓷基板;然而&#xff0c;由于国际上要求从产品中去除BeO的压力&#xff0c…