【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表达式检查一个整数是否大于5auto 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

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

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

相关文章

基于FPGA的累加器及数码管显示VHDL代码Quartus仿真

名称&#xff1a;基于FPGA的累加器及数码管显示VHDL代码Quartus仿真&#xff08;文末获取&#xff09; 软件&#xff1a;Quartus 语言&#xff1a;VHDL 代码功能&#xff1a; 累加器及数码管显示 1、可以通过按键输入1~9 2、数字输入后进行累加&#xff0c;将累加结果显示…

一文读懂Python的`__init__`,`__init__`方法的终极指南

大家好&#xff0c;今天给大家介绍一个Python中一个特殊的函数__init__。 在Python中&#xff0c;__init__方法是一个特殊的函数&#xff0c;它在创建类的新实例时自动调用。它的作用类似于其他编程语言中的构造函数&#xff0c;用于初始化对象的状态。这篇文章将带你深入了解…

经常发文章的你是否想过定时发布是咋实现的?

前言 可乐他们团队最近在做一个文章社区平台,由于人手不够,前后端都是由前端同学来写。后端使用 nest 来实现。 某一天周五下午,可乐正在快乐摸鱼,想到周末即将来临,十分开心。然而,产品突然找到了他,说道:可乐,我们要做一个文章定时发布功能。 现在我先为你解释一…

鸿蒙开发接口Ability框架:【@ohos.application.missionManager (missionManager)】

missionManager missionManager模块提供系统任务管理能力&#xff0c;包括对系统任务执行锁定、解锁、清理、切换到前台等操作。 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 impo…

windows 双网卡同时接入内外网

在公司使用wifi接入使用桌面云&#xff0c;但是公司wifi不能上外网&#xff0c;查资料不方便&#xff0c;通过手机同时接入外网。 同一台电脑设置同时连接内外网&#xff08;wifi或共享的网络&#xff09;_win7电脑同时使用手机和usb网卡使用wifi-CSDN博客 route print查看当前…

1天搞定SpringBoot+Vue全栈开发 (8)前端路由VueRouter(进行组件切换)

1.VueRouter安装与使用 2.参数传递 创建路由组件 在项目中定义Discover.vue、Friends.vue、My.vue三个组件&#xff0c;将来要使用vue-router来控制它们的展示与切换&#xff1a; Discover.vue <template><div><h1>发现音乐</h1></div> <…

【Git】Commit后进行事务回滚

起因 因为一直使用git add .&#xff0c;在学习pytorch中添加了一个较大的数据集后&#xff0c;导致git push失败&#xff0c;而这个大数据集并不是必须要上传到仓库的&#xff0c;但是因为自己在设置.gitignore前已经进行了git comit&#xff0c;所以&#xff0c;需要进行事务…

OpenHarmony 实战开发—— refreshlayout 组件开发学习指南~

1. RefreshLayout_harmonyos 功能介绍 1.1. 组件介绍&#xff1a; RefreshLayout_harmonyos 是一款下拉刷新组件 1.2. 手机模拟器上运行效果&#xff1a; 2. RefreshLayout_harmonyos 使用方法 2.1 在目录 build.gradle 下 implementation project(":refreshlayout_ha…

记一些内存取证题

生活若循规蹈矩&#xff0c;我们便随心而动 1.Suspicion 给了俩文件 python2 vol.py -f mem.vmem imageinfo 查看可疑进程 python2 vol.py -f mem.vmem --profileWinXPSP2x86 pslist 发现可疑进程TrueCrypt.exe 把这个进程提取出来。memdump -p 进程号 -D 目录 python2 vol…

Python读取ASC文件并转换成Excel文件(坐标)

import pandas as pd# 读取asc文件&#xff0c;指定空格为分隔符 df pd.read_csv(out_view2.asc, sep , headerNone)# 去掉空列 df df.dropna(howall, axis1)# 将数据保存到Excel文件 df.to_excel(out_view2.xlsx, indexFalse, headerFalse)效果图

Linux搭建http发布yum源

1、搭建http源yum仓库 &#xff08;1&#xff09;在yum仓库服务端安装httpd yum -y install httpd &#xff08;2&#xff09;修改配置文件 我们httpd 中默认提供web 界面的位置是我们/var/www/html 目录&#xff0c;如果我们yum 源想指定目录&#xff0c;就需要修改蓝框2处…

如何在低代码平台中引用 JavaScript ?

引言 在当今快速发展的数字化时代&#xff0c;企业对业务应用的需求日益复杂且多元。低代码开发平台作为一个创新的解决方案&#xff0c;以直观易用的设计理念&#xff0c;打破了传统的编程壁垒&#xff0c;让非技术人员也能轻松构建功能完备的Web应用程序&#xff0c;无需深入…