Effective STL: Item 44:优先使用与泛型算法同名的成员函数

Effective C++与现代C++实践:从RAII到智能指针的编程哲学 在C++编程中,资源管理和内存安全是构建健壮系统的核心基础。RAII(Resource Acquisition Is Initialization)作为一种关键编程范式,通过将资源生命周期与对象绑定,从根本上解决了资源泄露问题。这一原理在现代C++中通过智能指针(如std::unique_ptr、std::shared_ptr)得到了优雅实现,它们不仅自动管理动态内存,还通过所有权语义确保了异常安全。这些技术对于开发高性能服务器、游戏引擎等对稳定性要求极高的应用场景至关重要。本文以《Effective C+ 阅读详情
item 44:优先使用与泛型算法同名的成员函数
一些容器拥有和stl泛型算法同名的成员函数。关联容器提供count()、find()、lower_bound()、upper_bound(),和equal_range(),而list提供了remove()、remove_if()、unique()、sort()、merge(),和reverse()。这样做有两个理由。首先,成员函数更快。其次,它们与容器结合得更好(尤其是关联容器)。 那是因为同名的泛型算法和成员函数通常并不是以完全相同的方式来做同样的事。
我们以对关联容器的试验开始。假如有一个set<int>,它存储了一百万个元素,而你想找到元素727的第一个发生位置(如果它存在的话)。有两个最然的方法来执行搜索:
set<int> s; // create set, put
... // 1,000,000 values
// into it
set<int>::iterator i = s.find(727); // use find member
if (i != s.end()) ... // function
set<int>::iterator i = find(s.begin(), s.end(), 727); // use find algorithm
if (i != s.end()) ...
成员函数的find()运行对数时间,所以不管727是否存在于set中,set::find()只需执行不超过40次比较来查找它,而平均只需要20次。相比而言,泛型算法的find()运行线性时间,所以如果727不在set中时它需要执行1,000,000次比较。即使727在set中,也平均需要执行500,000次比较来定位它。效率得分如下:
成员的find():大约40(最坏情况)到大约20(平均情况)
泛型算法find():1,000,000(最坏情况)到500,000(平均情况)
和高尔夫比赛一样,分值低的赢。如你所见,比赛结果毫无争议可言。
我必须对成员函数的find()所需的比较次数表示小小的谨慎,因为它有些依赖于关联容器的实现。绝大部分的实现是使用的红黑树,平衡树的一种,失衡度可能达到2(that may be out of balance by up to a factor of two)。在这样的实现中,对一百万个元素的set进行搜索,所需的最大比较次数是38次。但对绝大部分的搜索情况而言,不超过22次。一个基于完全平衡树的实现绝不需要超过21次比较,但在实践中,完全平衡树的效率总得来说不如红黑树。这就是为什么绝大多数的stl实现都使用红黑树。
效率不是成员函数的find()和泛型算法find()间的唯一差别。如item 19所解释,stl泛型算法判断两个对象是否相同,检查的是equality(wq注:逻辑相等,使用operator==),而关联容器检测的是equivalence(wq注:数学相等,two elements are equal if neither is less than the other)。 因此,泛型算法find()搜索727用的是逻辑相等,而成员函数的find()用的是数学相等。逻辑相等和数学相等间的区别可以造成成功搜索和不成功搜索的区别。举例来说,item 19演示了用泛型算法find()在关联容器搜索失败而用成员函数的find()搜索却成功的情况!因此,如果操纵关联容器的话,你应该优先使用成员函数形式的find()、count()、lower_bound()等函数,而不是同名的泛型算法,因为这些成员函数版本提供了和其它成员函数相一致的行为。由于逻辑相等和数学相等间的差别,泛型算法不能提供这样的一致行为。
这一差别对map和multimap尤其明显,因为它们容纳的是pair型对象,而它们的成员函数只在意pair对象的key部分。因此,成员函数count()只统计key值匹配的pair对象的数目 (“匹配”,自然是检测含义相等);pair的value部份被忽略。成员函数的find()、lower_bound()、upper_bound(),以及equal_range()同样如此。如果你使用泛型算法find(),于是,它的寻找将基于(a)逻辑相等和(b)pair的全部组成部分;泛型算法的find()、lower_bound()等同样如此。要想让泛型算法只关注于pair的key部分,必须要跳出item 23描述了的限制(那儿介绍了用数学相等代替逻辑等价作测试的方法)。
另一方面,如果你真的关心效率,你可以决定采用item 23中的技巧,协同item34中讲的对数时间搜索算法。相对于性能的提升,这只是一个很小的代价。再者,如果你真的在乎效率,你应该考虑非标的hash容器(在item 25进行了描述),只是,你将再次面对逻辑相等和数学相等的区别。
对于标准的关联容器,选择成员函数而不是泛型算法,有几个好处。首先,你得到的是对数时间而不是线性时间的性能。其次,你判断两个元素“相同”使用的是数学相等,这是关联容器的默认定义。第三,当操纵map和multimap时,你自动地只处理key值而不是(key, value)对。这三点给了优先使用成员函数充分的理由。
让我们转到list的与泛型算法同名的成员函数身上。这里的故事几乎全部是关于效率的。每个被list作了特别化的泛型算法(remove()、remove_if()、unique()、sort()、merge(),和reverse())都要拷贝对象,而list的特别版本不拷贝任何东西;它们只是简单地操纵连接list的节点的指针。泛型算法和成员函数的算法复杂度是相同的,但如果操纵指针比拷贝对象的代价小的话,list的版本应该提供更好的性能。
牢牢记住这一点很重要:list的成员函数版本的行为和同名的泛型算法版本,行为经常不相同。如item 32所解释,调用泛型算法的remove()、remove_if(),和unique(),必须紧跟着调用erase()函数(如果你真的想从容器中清除对象的话);但list的remove()、remove_if()和unique()成员函数真的去掉了元素,不需要接着调用erase()。
在泛型算法sort()和list的sort()成员函数间的一个重要区别是:前者不能用于list。作为单纯的双向iterator,list的iterator不能传给泛型算法sort()。merge()泛型算法和list的merge()成员函数之间也同样存在巨大差异。这个泛型算法不被允许修改源范围,但list::merge()同样可以修改它的宿主list。
所以,你明白了吧。 当面临在同名的stl泛型算法和容器成员函数间进行选择时,你应该优先使用成员函数。它几乎肯定更高效,而且它看起来和容器的惯常行为集成得更好
 
C++ 知识补充 向量(vector)是一个封装了动态大小数组的顺序容器(SequenceContainer)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。C++中map提供的是一种键值对容器,里面的数据都是成对出现的,如下图:每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。 阅读详情

相关推荐

Effective STL读书笔记

没有c++程序不使用STL,这是一本讲述如何正确高效地使用STL的参考书。 STL的核心是容器和算法,有了一定的使用经验之后,本书可以作为技术提升的点睛之笔。 本书成文较早,技术已经发生了较大的变化,取其精华。 容器 慎重选择容器类型。 标准STL序列容器:vector, string, deque, list。 标准STL关联容器:set, multiset, map, multimap...

guotianqing的博客 488

mybatis 同名方法_STL算法和容器中的成员方法同名时,该如何选择?

通过前面的学习,我们已经掌握了一些 STL 算法的功能和用法。值得一提的是,STL 标准库提供有 70 多种算法函数,其中有些函数名称和 STL 容器模板类中提供的成员方法名相同。例如,STL 标准库提供了 sort() 和 merge() 函数,而 list 容器模板类中也提供有同名的 sort() 和 merge() 成员方法。再比如,STL 标准库提供有 count()、find()、low...

weixin_39796149的博客 271

【信息科学与工程学】【审计学】第一篇 招投标领域审计算法01

在每个关键流程节点(如文件上传、开标唱标、评标结束), 计算该环节所有电子文件的数字指纹(如SHA-256哈希值), 并将指纹和元数据(时间、操作人)上链存证。:从发票、合同中提取材料品名、规格、采购价、时间、地点。:对每个供应商, 提取其在历史投标中的行为序列特征, 如:中标率、与特定伙伴同时投标率、自身高报价次数、在伙伴中标项目中的“弃标”或“无效标”次数。:监控开标、评标现场音视频, 识别异常情绪(激烈争吵)、敏感关键词(“打点”、“关照”)、异常物品传递、私下交流等违规行为。

weixin_49199313的博客 812

44. 容器的成员函数优先于同名的算法

有些STL 容器提供了一些与算法同名的成员函数。大多数情况下,应该使用这些成员函数,而不是相应的STL算法。 有两个理由: 成员函数往往速度快。 成员函数通常与容器结合地更紧密,这是算法所不能比的。 set容器的find成员函数以对数时间运行,而find算法以线性时间运行。 效率并不是find成员函数和find算法之间的唯一差别。STL算法以相同性而判断两个对象是否具有相同的值,而关联容器使用...

xupeng1644的博客 1516

5个4000比特大状态置换算法的设计与分析

下面是 5 个概念性、实验性的 4000 位可逆置换设计。它们都保证是双射,但未经过密码分析,不可直接用于生产系统。风格分别覆盖:三维 SPN、Feistel、可逆元胞自动机、ARX、宽轨迹/Keccak 式结构。 这 5 个设计分别代表了 SPN、Feistel、元胞自动机、ARX、宽轨迹 Keccak 五种不同风格,覆盖了主流大状态置换的构造思路。再次强调:它们只是实验性概念,若要用于实际协议,必须经过严格安全性分析。

HuangJinLong2的博客 345

树莓派 SPI操作

扩展板配备一款0.96inch,128864分辨率的oled显示屏,通过SPI控制,先上显示效果图。由于程序过长,在这里我就不把代码全部贴出来了,只是简单讲解一下spi的操作函数。管脚如下如所有,左边方框的管脚分别为MOSI MISO SCLK,左边CE0,CE1为两个片选管脚,分别对应上图中的spidev0.0,spidev0.1两个设备。下载spidev库,复制到树莓派,并行运行如下命令解压安装。spi设备,此处设备为/dev/spi-decv0.0。在/dev路径下面,我们可以发现两个spi设备。

weixin_46529898的博客 914

Effective_STL 学习笔记(四十四) 尽量使用成员函数代替同名的算法

有些容器拥有和 STL 算法同名的成员函数。 关联容器提供了 count、find、lower_bound、upper_bound 和 euqal_range list 提供了 remove、remove_if、unique、merge 和 reverse 大多数时候应该用成员函数代替手写算法,这样做的两个理由:   比起算法,它们与容器结合的更好(尤其是关联容器)  ...

weixin_33753003的博客 169

电商订单系统设计简析(一)

电商所有模块中,订单系统作为最为核心的模块,决定了整个流程能不能顺畅的执行,起着承上启下的作用。相信很多PM都不陌生,到了一家电商公司,总会觉得公司现有的流程有不少问题,因为问题来自四面八方,一下子摸不着到底是哪里出了问题,PM就跟补丁师傅一样,遇到一个补一个。其实很多日常开发和测试提得需求都是表面需求,而这些表面上呈现出的各种问题,都是源自于流程上的不完整或者流程上某个环节上的缺失导致的。订单系...

野蛮非先生的博客 9553

effective stl 第44条:容器的成员函数优先于同名的算法

有些容器提供了一些与算法同名的成员函数,比如:关联容器提供了count/find/lower_bound/upper_bound和equal_range,而list则提供了remove/remove_if/unique/sort/merge/reverse.在多数情况下,应该使用成员函数。原因是:1、成员函数速度快。2.成员函数与容器结合的更加紧密,这是算法不能比的,并且同名的算法和成员函数所做的事

sun%moon 472

Python爬虫实战:从巨潮资讯网高效获取结构化JSON数据

在数据采集与处理领域,网络爬虫是实现自动化信息获取的核心技术。其基本原理是通过模拟浏览器行为,向目标服务器发送HTTP请求并解析响应内容,从而提取所需数据。相较于传统的网页解析,直接获取结构化数据(如JSON格式)能极大提升数据处理的效率与准确性,避免了复杂的HTML解析或PDF文本提取过程。这一技术价值在金融数据分析、市场研究、舆情监控等场景中尤为突出,能够快速构建高质量的数据集。本文以Python爬虫为例,聚焦于从巨潮资讯网这类官方信息披露平台,精准定位并抓取JSON格式的上市公司年报数据,详细阐述了接

weixin_29243279的博客 1417

AD9371 官方例程构建及单音信号收发

项目构建基本流程和AD9361差不多,由于官方使用的ZCU102,记录下移植遇到的一些问题最终接收到正确的正弦波Errors: 0Errors: 0Errors: 0Errors: 0AD9361。

weixin_44630490的博客 2971

C++AI编译错误自动修复神器-告别手动Debug的终极方案

在日常 C++ 开发中,编译错误是最频繁遇到的障碍之一。一个中等规模的项目在重构期间,一次 可能产生数十甚至上百条错误信息。这些错误往往具有级联效应——一个头文件的拼写错误可能导致下游十几个翻译单元同时报错,而真正需要修改的地方只有一处。传统的工作流是: 这个循环对于经验丰富的开发者来说尚可接受,但对于以下场景则效率极低:优势:局限:本项目最适合以下场景:阅读

weixin_48053866的博客 279

ISA-95(S95)标准详解

ISA-95是制造业系统集成的“通用语言”,通过分层模型和信息流规范,打通企业计划层与设备控制层,成为实现数字化工厂的核心标准之一。其与ISA-88的协同应用,可进一步优化生产执行与资源管理的效率。标准,旨在解决企业商业系统(如ERP)与工业控制系统(如MES、SCADA)之间的集成问题。

「东哥说MES」 专注于MES制造执行系统,为你拆解核心架构、功能模块及与ERP/PLC的集成逻辑。提供从入门到精通的系列干货、精选行业报告与实用工具,构建你的数字化知识体系,关注我,用实战经验照亮你的数字化之路。 3737

44 容器的成员函数优先于同名的算法

成员函数往往速度快。成员函数通常与容器(特别是关联容器)结合的更加紧密。关联容器,假设一个set容,其中包含一百万个值,现在查找727这个值是否包含在容器中set&lt;int&gt; s; //创建set,并放入一百万个值 ... set&lt;int&gt;::iterator it = s.find(727); //使用find成员函数 if(it != s.end()) ...

hallå的博客 253

YOLO11实战优化:暗光环境检测 | 引入Retinex增强模块与YOLO11联合训练,解决夜间/低照度场景抓拍痛点

本文探讨了暗光环境下目标检测的技术挑战与解决方案。研究发现,传统CNN模型在低照度条件下性能显著下降,主要由于光子数减少导致信噪比降低、目标特征被噪声淹没。针对这一问题,文章提出将可微分光照增强模块嵌入YOLO检测器的技术路线,重点分析了Retinexformer+YOLO11联合方案的优势。 文章对比了YOLO系列模型在暗光场景的表现,指出YOLO11凭借其C3k2模块、无锚检测头和多任务统一骨干网络,在低对比度图像特征提取方面优于前代产品。同时详细介绍了Retinexformer的理论基础和技术创新,包

2601_95807009的博客 206

Euro-NCAP-HWA测试流程中文版V1.1(2023发布)

在本协议中,使用了以下术语:Vehicle undertest (VUT) – 指根据本规程测试的车辆,车上有碰撞前的碰撞缓解或避免系统Global VehicleTarget (GVT) – 指本协议中使用的车辆目标,其定义见TB025—Euro-NCAP全球车辆目标规范v1.0辅助其他车辆(SOV)--指最新的 AEB VRU 测试规程中定义的 "大型障碍车辆"(而非机器人控制的平台),用于本规程中的 "切出 "测试。Time To Collision (TTC) – 指在VUT碰撞GVT之前的剩余时间

小明师兄的博客 595

【C++ STL学习笔记】C++ STL常用算法(排序、合并、搜索和分区)

文章目录C++ sort()排序函数用法详解C++ sort()排序函数C++ stable_sort()用法详解C++ partial_sort()函数详解C++ partial_sort()排序函数C++ partial_sort_copy()排序函数C++ STL标准库这么多排序函数,该如何选择?自定义STL算法规则,应优先使用函数对象!C++ merge()和inplace_merge()函数用法(详解版)C++ merge()函数C++ inplace_merge()函数C++ find()函数用

qq_41854911的博客 2106

VEML7700环境光传感器原理图设计,已量产(光线传感器)

最近做便携显示设备的自动亮度调节模块,最终敲定了 VEML7700 这款数字光传感器 —— 一是它 0~120klx 的宽量程刚好覆盖 “暗室→户外强光” 的全场景,二是 Filtron™技术让它的光谱响应和人眼高度贴合,测出来的 “亮度” 更符合实际视觉感受,加上 O-Trim™技术把输出公差压到 10% 以内,省了不少后期校准的功夫。搭好电路后串口直接读 lx 数值,稳定性和精度都够,这篇聊聊这个模块的硬件设计细节。

不脱发的程序猿 599

容器中的find成员函数与algorithm库中的find方法

1、find成员函数 string、map、set等容器有find成员函数,因此可以直接用来查找容器中的成员。 map<int,int> myMap; myMap[1] = 3; myMap[4] = 6; auto ptr = myMap.find(1); if(ptr == myMap.end()){ cout<<"容器中不存在键为1的元素" } 2、find库方法: list、vector等容器没有find成员函数,因此必须借助algorithm库中的find方法查找容器中

个人工作中学到的专业技术与职业发展知识笔记 709

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

条款44:尽量用成员函数代替同名的算法

有些容器拥有和STL算法同名的成员函数。关联容器提供了count、find、lower_bound、upper_bound和equal_range,而list提供了remove、remove_if、unique、sort、merge和reverse。大多数情况下,你应该用成员函数代替算法。这样做有两个理由。首先,成员函数更快。其次,比起算法来,它们与容器结合得更好(尤其是关联容器)。那是因为同名的...

weixin_33843947的博客 155

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 187

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【算法拾光】链表 哈希表|K个一组翻转链表 + 两数之和

K个一组翻转链表需分段反转,借助哑节点与前驱指针维护连接,避免断链;两数之和利用哈希表实现O(1)查找,空间换时间,高效定位目标组合。前者考察链表指针操作,后者聚焦映射关系构建,均为面试高频题。

wuqingyigexiaoba的博客 274

排序算法深度笔记(下):非比较类排序的线性突破与工程边界

排序算法时间复杂度额外空间复杂度稳定性是否基于比较选择排序O(N^2)(O(1))不稳定是冒泡排序O(N^2)(O(1))稳定是插入排序O(N^2)(O(1))稳定是归并排序O(N\log N)(O(N))稳定是快速排序O(N\log N)O(log N)不稳定是堆排序O(N\log N)O(1)不稳定是计数排序(O(N + M))O(M))稳定否基数排序O(N)稳定否桶排序平均O(N) / 最坏O(N^2)

2401_87069538的博客 557

算法日常・每日刷题--<动态规划>42

本题为“不相交的线”,与最长公共子序列问题相似。使用动态规划求解:定义 dp[i][j] 表示 nums1[0:i] 与 nums2[0:j] 的最大不相交连线数。若元素相等,则继承左上值加1;否则取上方或左方最大值。最终返回 dp[m][n],即两数组的最大不相交连线数。时间复杂度 O(mn),空间复杂度 O(mn)。

2503_92261635的博客 19

C语言程序设计题|有序数组插入数字冒泡排序

题目要求将一个数插入有序数组末尾,并用冒泡排序实现整体升序。代码先将输入数存入数组最后位置,再通过双重循环进行冒泡排序,每轮将较大元素向后移动,最终输出11个升序元素。该方法虽时间复杂度为O(n²),但符合题目要求,逻辑清晰,适合初学者理解排序原理。

2301_81429079的博客 643
上一篇: 关于“内存对齐”
下一篇: C++中的内存划分
AlwaysSLH
博客等级 码龄20年 63粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值