【C++泛型编程】(二)标准模板库 STL

文章目录

  • 标准模板库 STL
    • 容器
    • 算法
    • 迭代器
    • 仿函数/函数对象
    • 适配器
    • 分配器
    • 示例

标准模板库 STL

C++ 的标准模板库(Standard Template Library,STL)旨在通过模板化的设计,提供一种通用的编程模式,使程序员能方便地实现和扩展各种数据结构和算法,提高程序的开发效率和执行效率。STL 的设计遵循泛型编程的原则,其组件可以处理各种类型的数据。

STL 中的组件包括容器(containers)、迭代器(iterators)、算法(algorithms)、仿函数/函数对象(function objects)、适配器(adaptors) 和分配器(allocators)。他们的关系如图所示:

容器负责存储数据,算法用于执行数据处理操作,迭代器为算法提供数据访问机制,仿函数用于定义算法的行为策略,适配器用于修改和扩展接口,而分配器用于管理内存资源,

容器

容器是一组模板类,内部封装了数据的存储和访问机制,对外部提供了统一的接口。在STL中,容器被分为两大类:序列式容器(Sequence Containers)和关联式容器(Associative Containers)。

序列式容器用于存储具有严格线性关系的元素序列。它们以线性方式存储元素,可以动态地添加、删除和访问元素。序列式容器主要有以下几种:

  • std::vector:动态数组,可以存储相同类型的元素。支持随机访问元素,但在数组中间插入或删除元素可能会导致大量的元素移动。
  • std::deque:双端队列,具有在两端添加和删除元素的高效性。与std::vector类似,但支持更高效的头部插入和删除。
  • std::list:双向链表,元素在内存中不是连续存储的。在链表的任何位置添加或删除元素都非常高效,但随机访问元素效率较低。
  • std::forward_list(C++11起):单向链表,与std::list类似,但只支持向前迭代。
  • std::array(C++11起):固定大小的数组,不支持动态大小调整。提供与原生数组类似的性能,但具有STL容器的接口。
  • std::string:虽然std::string主要用于处理字符串,但它在内部实际上是一个特化的std::basic_string模板,因此也可以被视为一种序列式容器。

关联式容器存储的元素具有键值对(key-value pair)的关联关系。关联式容器内部通常使用红黑树(对于有序的容器)或哈希表(对于无序的容器)来实现,以支持高效的查找、插入和删除操作。关联式容器主要有以下几种:

  • std::set:集合,包含唯一的元素,元素在容器中按升序排列。
  • std::multiset:多重集合,允许存储重复的元素,元素在容器中按升序排列。
  • std::map:映射,存储键值对,其中键(key)是唯一的,并且按键的升序存储。
  • std::multimap:多重映射,允许存储具有相同键的多个键值对,并且按键的升序存储。
  • std::unordered_set(C++11起):无序集合,与std::set类似,但元素的顺序不保证。它使用哈希表来实现,因此插入、删除和查找操作的平均时间复杂度都是O(1)。
  • std::unordered_multiset(C++11起):无序多重集合,与std::multiset类似,但元素的顺序不保证。
  • std::unordered_map(C++11起):无序映射,与std::map类似,但元素的顺序不保证。它使用哈希表来实现,因此操作效率更高。
  • std::unordered_multimap(C++11起):无序多重映射,与std::multimap类似,但元素的顺序不保证。

算法

算法是处理数据的函数或函数模板,它们不存储数据,而是对数据进行操作。算法通过迭代器从容器中获取数据,并执行相应的操作。STL算法的头文件主要包括<algorithm><numeric><functional>。以下是一些常用的STL算法:

遍历算法

  • for_each:对容器中的每个元素执行指定的操作。

查找算法

  • find:在容器中查找等于指定值的元素。
  • find_if:在容器中查找满足特定条件的第一个元素。
  • adjacent_find:查找相邻的重复元素或满足特定条件的相邻元素对。
  • binary_search:在已排序的范围内查找指定元素。
  • count:计算容器中等于指定值的元素个数。
  • count_if:计算容器中满足特定条件的元素个数。

排序算法

  • sort:对容器中的元素进行排序。
  • random_shuffle:随机打乱容器中的元素顺序(注意:C++17开始已被弃用,推荐使用其他方式实现随机排序)。
  • merge:合并两个已排序的范围。
  • reverse:反转容器中的元素顺序。

拷贝和替换算法

  • copy:从一个位置拷贝元素到另一个位置。
  • replace:替换容器中等于指定值的元素。
  • replace_if:替换容器中满足特定条件的元素。
  • swap:交换两个元素的值。

算术生成算法

  • accumulate:计算容器中元素的累积和(或其他二元操作的累积结果)。
  • fill:用指定值填充容器中的元素。

集合算法

  • set_intersection:计算两个已排序集合的交集。
  • set_union:计算两个已排序集合的并集。
  • set_difference:计算两个已排序集合的差集(第一个集合中存在但第二个集合中不存在的元素)。

迭代器

迭代器是访问容器中元素的指针或类似指针的对象。 迭代器允许算法间接访问和操作容器中的元素。 容器可以通过返回迭代器的方式向算法暴露其内部元素。

仿函数/函数对象

仿函数/函数对象是一个行为类似于函数的对象,可以被调用,并且可以在泛型编程中用作函数参数,用于定义算法的行为策略 (允许我们为算法提供自定义的比较、判断或操作规则)。 在C++中,仿函数可以通过函数指针、函数对象(重载了函数调用运算符operator()的对象)、以及C++11引入的lambda表达式来定义。

适配器

适配器用于修改或扩展已有组件的接口,使它们能够更好地适应不同的使用场景。 STL中主要包括容器适配器,迭代器适配器和仿函数适配器。

容器适配器 提供了一种机制,用于修改或扩展容器的行为。STL提供了三种容器适配器:stack(栈)、queue(队列)和priority_queue(优先队列),其中stackqueue分别提供了栈和队列的数据结构,而priority_queue则允许元素根据优先级进行排序。

迭代器适配器(Iterator Adapters) 提供了一种机制,可以将非迭代器对象转换为迭代器对象,或者改变迭代器的行为。STL中的迭代器适配器包括back_insert_iteratorfront_insert_iteratorinsert_iterator等。这些适配器分别提供了在容器的末尾、开头或任意位置插入元素的功能。

函数对象适配器 STL中的函数函数适配器包括bindmem_funmem_fun_ref等。这些适配器可以将成员函数、函数指针或其他可调用对象转换为函数对象,以便与STL算法一起使用。

分配器

分配器在容器的创建和销毁过程中起着关键作用,它们负责为容器分配和回收内存资源。 STL容器默认使用标准分配器std::allocator,但也可以自定义分配器来满足特定的内存管理需求。

示例

下面是一个STL的使用示例,它使用了std::vector(容器)、迭代器、std::find_if(算法)、lambda函数(函数对象)、默认的std::allocator(隐式使用),以及std::stack(容器适配器):

#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>

int main() {
    // 容器: 使用vector容器存储整数
    std::vector<int> numbers = {1, 5, 8, 3, 9, 2};
    // 迭代器: 使用迭代器(指针)遍历vector  
    // 1. 获取vector的begin()和end()迭代器  
    // 2. 使用迭代器 it 遍历容器中的元素,直到达到end()迭代器  
    for (std::vector<int>::iterator it = numbers .begin(); it != numbers .end(); ++it) {  
        std::cout << *it << " ";  
    } 
    std::cout << std::endl;
    
    // 函数对象: 使用lambda表达式检查一个整数是否大于5
    auto is_greater_than_five = [](int num) { return num > 5; };

    // 算法: 使用find_if查找第一个大于5的数, it也为迭代器(指向结果的指针)
    auto it = std::find_if(numbers.begin(), numbers.end(), is_greater_than_five);

    if (it != numbers.end()) {
        std::cout << "Found a number greater than 5: " << *it << std::endl;
    } else {
        std::cout << "No number greater than 5 found." << std::endl;
    }

    // 容器适配器: 使用stack适配器(基于vector)
    std::stack<int, std::vector<int>> numStack;

    // 将vector中的元素压入stack中(这里为了演示,只压入找到的那个大于5的数)
    if (it != numbers.end()) {
        numStack.push(*it);
    }

    // 弹出stack中的元素并打印
    while (!numStack.empty()) {
        std::cout << "Popped from stack: " << numStack.top() << std::endl;
        numStack.pop();
    }

    // 分配器: vector默认使用std::allocator,而stack适配器也使用其底层容器的分配器
    return 0;
}
1 5 8 3 9 2 
Found a number greater than 5: 8
Popped from stack: 8

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

栈实现队列

一、分析 栈的特点是先出再入&#xff0c;而队列的特点为先入先出&#xff0c;所以我们创造两个栈&#xff0c;一个用来存放数据&#xff0c;一个用来实现其它功能此时栈顶为队尾&#xff1b;当要找队头数据时将前n-1个数据移入到另一个栈中&#xff0c;此时剩余那个数据为队头…

通义灵码企业版正式发布,满足企业私域知识检索、数据合规、统一管理等需求

5 月 9 日阿里云 AI 峰会&#xff0c;阿里云智能集团首席技术官周靖人宣布&#xff0c;通义灵码企业版正式发布&#xff0c;满足企业用户的定制化需求&#xff0c;帮助企业提升研发效率。 通义灵码是国内用户规模第一的智能编码助手&#xff0c;基于 SOTA 水准的通义千问代码模…

永久免费的多域名通配符SSL证书申请流程

如果拥有多个域名&#xff0c;且有部分域名拥有子域名&#xff0c;那么多域名通配符证书是非常合适的选择。预算有限或者前期测试可以考虑免费版本的&#xff0c;国产证书厂商JoySSL则提供免费的多域名通配符证书 。 具体流程如下 1创建管理账号 登录JoySSL官网&#xff0c;创…

小程序地理位置接口申请教程来啦4步学会

小程序地理位置接口有什么功能&#xff1f; 如果我们提审后驳回理由写了“当前提审小程序代码包中地理位置相关接口( chooseAddress、getLocation )暂未开通&#xff0c;建议完成接口开通后或移除接口相关内容后再进行后续版本提审”&#xff0c;如果你也碰到类似问题&#xff…

LED液晶显示屏(LCD/TFT)抗干扰太阳光模拟器

LED&液晶显示屏(LCD/TFT)抗干扰太阳光模拟器&#xff1a;解决驾驶员视线问题 在驾车过程中&#xff0c;太阳光的干扰是一个常见的问题。特别是在高速公路等需要高度集中注意力的情况下&#xff0c;太阳光的干扰会严重影响驾驶员的视线&#xff0c;增加驾驶风险。为了解决这…

视频剪辑达人分享:一键批量置入随机封面,创意无限

在数字化媒体飞速发展的今天&#xff0c;视频内容已经成为我们表达创意、分享故事、传递信息的主要方式之一。而在视频制作过程中&#xff0c;封面作为视频的“脸面”&#xff0c;往往决定了观众是否愿意点击观看。因此&#xff0c;为视频选择合适的封面变得至关重要。 在大量…

springboot3 集成spring-authorization-server (一 基础篇)

官方文档 Spring Authorization Server 环境介绍 java&#xff1a;17 SpringBoot&#xff1a;3.2.0 SpringCloud&#xff1a;2023.0.0 引入maven配置 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

TMS320F280049 CLB模块--LUT4 OUTLUT(4)

LUT4 示意图如下&#xff1a; OUTLUT 示意图如下&#xff1a; 寄存器 参考文档&#xff1a; TMS320F28004x Real-Time Microcontrollers Technical Reference Manual (Rev. G)

2024第十六届“中国电机工程学会杯”数学建模A题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

Apache ECharts

Apache ECharts介绍&#xff1a; Apache ECharts 是一款基于 Javascript 的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。 官网地址&#xff1a;https://echarts.apache.org/zh/index.html Apache ECh…

上线了《學點笔录》,更方便翻阅笔录

大家好&#xff0c;我是学点&#xff0c;整理了一下自己笔记、摘要、记录《學點笔录》并且上线了为更方便翻阅 https://code.yellowcan.cn 欢迎来我的學點笔录网站&#xff01;笔录会关于与编程有关&#xff0c;比如bug记录、bug解决过程、编程笔记等等&#xff0c;帮助回忆阅…

示例六、湿敏传感器

通过以下几个示例来具体展开学习,了解湿敏传感器原理及特性&#xff0c;学习湿敏传感器的应用&#xff1a; 示例六、湿敏传感器 一、基本原理&#xff1a;随着人们生活水平的不断提高&#xff0c;湿度监控逐步提到议事日程上。由于北方地区秋冬季干燥&#xff0c;需要控制室内…

mamba复现—mamba+yolov8魔改(win)

Mamba复现出现的问题 安装下列步骤一步步走 一、 注&#xff1a;若是Windows环境下python一定是3.10版本的&#xff0c;要不然trition无法安装 conda create -n mamba python3.10 conda activate mamba conda install cudatoolkit11.8 -c nvidia pip install torch2.1.1 t…

在MyBatis中,如何将数据库中的字符串类型映射为枚举类型?

在MyBatis中&#xff0c;如何将数据库中的字符串类型映射为枚举类型&#xff1f; 网上看了很多教程。说了很多&#xff0c;但是都没说到重点&#xff01; 很简单&#xff0c;xml文件中&#xff0c; 使用resultType&#xff0c;而不是使用resultMap就可以了。 resultType"…

示例七、超声波传感器测距

通过以下几个示例来具体展开学习,了解超声波传感器原理及特性&#xff0c;学习超声波传感器的应用&#xff1a; 示例七、超声波传感器测距 一、基本原理&#xff1a; 1、超声波测距仪的系统结构 利用超声测距原理测量物体之间的距离&#xff0c;当此距离小于某一设定值时&…

信创 | 高效信创项目管理:关键步骤与实用技巧!

高效信创项目管理的关键步骤与实用技巧可以从多个维度进行分析和总结。首先&#xff0c;建立有效的工程管理体系是确保信创项目顺利实施的基础&#xff0c;这包括项目管理、质量管理、成本控制等方面的工作。其次&#xff0c;实现项目全流程精细化管理&#xff0c;如信息的及时…

028.实现 strStr()

题意 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 难度 简单 示例 例 1 输入&#xff1a;hays…

Day 44 完全背包理论基础 518. 零钱兑换 II 377. 组合总和 Ⅳ

完全背包理论基础 ​ 完全背包和0-1背包的最大区别在于完全背包里的每个物品的数量都是无限个&#xff0c;而0-1背包每个物品只有一个&#xff1b; 内嵌循环遍历顺序 ​ 回顾一维数组0-1背包的遍历递推公式&#xff1a; for (int i 0&#xff1b; i < weight.size(); i)…

线程知识点

一、线程 1.定义 线程&#xff1a;是一个进程并发执行多种任务的机制。 串行&#xff1a;多个任务有序执行&#xff0c;一个任务执行完毕后&#xff0c;再去执行下一个任务 并发&#xff1a;多个任务在单个CPU上运行&#xff0c;同一个时间片上只能运行一个任务&#xff0c;c…

漫谈AI时代的手机

以chatGPT 为代表的大语言的横空出世使人们感受到AI 时代的到来&#xff0c;大语言模型技术的最大特点是机器开始”懂人话“&#xff0c;”说人话“了。如同任何一个革命性工具的出现一样&#xff0c;它必将改变人类生活和工作。 在这里。我谈谈AI时代的手机。 语音通信的历史…