发布时间:2026/8/31 4:57:50
C++11 工程级应用 06:自己造一个类似Python的Range迭代器 C11 工程级应用 06自己造一个类似Python的Range迭代器Bilibili 同步视频一、先回顾基于范围的 for 循环到底是什么二、迭代器的接口该怎么设计三、实现 Range 容器外壳 impl 类四、封装对外的 range 函数模板五、完整测试体验效果六、总结 拓展思考摘要C11 推出的基于范围的 for 循环range‑based for用起来十分清爽但很多人只知道拿它遍历 STL 容器。你有没有想过如何让自定义类型也支持这个语法甚至手写一个类似 Python 的range()直接写for(auto n : range(2,8,2))完成区间迭代今天我们就从底层原理到完整实现一步步拆解这个有趣的小轮子。Bilibili 同步视频C11 工程级应用 06自己造一个类似Python的Range迭代器一、先回顾基于范围的 for 循环到底是什么很多同学写 C11 之后的代码经常写出这样赏心悦目的代码std::vectorintvec{1,2,3,4,5};for(autov:vec){std::coutv ;}对比老式迭代器写法代码简洁度直接拉满。但很多人只知其然不知其所以然。本质基于范围的 for 循环只是编译器提供的语法糖。编译器会在背后帮你去找对象的begin()与end()迭代器然后转换成普通迭代器循环。⚠️重要避坑提醒尽量不要在基于范围的 for 迭代过程中修改被迭代的容器增删元素。一旦迭代器失效会产生未定义行为。业务代码优先规避如果业务场景不得不修改容器一定要理解迭代器失效规则提前做好逻辑防护。那编译器是按什么规则去找begin和end呢优先级分为 3 条如果是原生数组begin就是数组首地址end是首地址 数组长度如果是类对象优先调用类内部的成员函数begin()、end()获取迭代器如果类没有提供成员版本则尝试查找全局命名空间下的begin()、end()函数。划重点想要自定义类型支持**for(xxx : obj)语法核心就是提供合法的begin()和end()****返回能够做迭代对比的迭代器对象。**日常开发中STL 的vector、map、list都已经内置这套接口开箱即用。但有些场景我们并不想迭代一个实实在在存放数据的容器只是想迭代一段区间例如// 输出246for(intn2;n8;n2){std::coutn ;}上面代码逻辑很简单区间[2,8)步长为2。在Python中我们可以优雅写for n in range(2,8,2)。但原生C标准库并没有提供这样的range工具只能手写普通for循环。那我们能不能自己造一个轮子实现C版本的range实现下面这样的效果// 我们想要的效果for(auton:range(2,8,2)){std::coutn ;}答案是完全可以接下来我们动手造轮子。二、迭代器的接口该怎么设计想要实现range首先需要实现专属迭代器。基于范围的 for 循环迭代时只会做几件事解引用*it取值、前置自增it、使用!做结束判断。小知识点range‑for并不会用到****、、等运算符只要求实现operator!和前置operator可以少写很多代码。这里有一个非常关键的思考点迭代器之间比较我们应该比较什么如果直接拿迭代器保存的数值做!判断会踩大坑举个例子区间[2,8)步长 3。序列是2、5下一个值是 8。但是(8‑2)/3 2刚好整除还好如果区间[2,9)步长 3序列 2、5、8。但如果步长不能被区间差值整除单纯对比 value 值!判断会失效。✅ 解决方案不对比迭代器内部数值而是维护一个迭代计数器 cursor游标。拿游标做不等判断而不是拿实际迭代的值。cursor记录当前是第几次迭代value_保存当前迭代产出的值step_保存步长迭代过程中不可修改设置为const迭代器基础骨架namespacedetail_range{templatetypenameTclassiterator{public:usingvalue_typeT;usingsize_typesize_t;private:size_type cursor_;// 迭代游标用来判断结束constvalue_type step_;// 步长不可修改value_type value_;// 当前迭代值public:iterator(size_type cur_start,value_type begin_val,value_type step_val):cursor_(cur_start),step_(step_val){value_begin_valstep_*cursor_;}// 解引用获取值value_typeoperator*()const{returnvalue_;}// 只需要实现!range‑for只调用!booloperator!(constiteratorrhs)const{returncursor_!rhs.cursor_;}// 前置range‑for只用前置iteratoroperator(){value_step_;cursor_;return*this;}};}// namespace detail_range关键逻辑构造函数传入初始游标、起始值、步长直接计算出初始 value每次值增加步长游标 1比较迭代器是否结束仅仅对比cursor_。这样不管步长是正数、负数、小数都不会出现终止条件错乱的问题。三、实现 Range 容器外壳 impl 类迭代器写好了还需要一个 “容器外壳” 对象给外部提供begin()与end()成员函数供 range‑for 调用。我们把这个外壳命名为implT。这个对象仅仅保存区间配置起点、终点、步长、最大迭代次数并不存储所有迭代元素属于惰性迭代没有内存开销性能非常优秀。成员全部使用const修饰对象构造完成之后参数就不能修改。内部需要一个私有函数get_adjusted_count()计算最大迭代次数max_count_做合法性校验正向迭代步长 0 时终点必须大于起点反向迭代步长 0终点必须小于起点非法直接抛异常。计算迭代次数向上取整处理不能整除的场景。namespacedetail_range{templatetypenameTclassimpl{public:usingvalue_typeT;usingreferenceconstvalue_type;usingconst_referenceconstvalue_type;usingiteratorconstiteratorT;usingconst_iteratorconstiteratorT;usingsize_typetypenameiterator::size_type;private:constvalue_type begin_;constvalue_type end_;constvalue_type step_;constsize_type max_count_;size_typeget_adjusted_count()const{if(step_0begin_end_){throwstd::logic_error(End value must be greater than begin value.);}elseif(step_0begin_end_){throwstd::logic_error(End value must be less than begin value.);}size_type xstatic_castsize_type((end_-begin_)/step_);if(begin_(step_*x)!end_){x;}returnx;}public:impl(value_type begin_val,value_type end_val,value_type step_val):begin_(begin_val),end_(end_val),step_(step_val),max_count_(get_adjusted_count()){}size_typesize()const{returnmax_count_;}const_iteratorbegin()const{returnconst_iterator(0,begin_,step_);}const_iteratorend()const{returnconst_iterator(max_count_,begin_,step_);}};}// namespace detail_range性能说明impl 对象只是保存 3 个数值 1 个计数值迭代器也只有简单数值成员。整个 range 不分配堆内存没有存储全部序列属于惰性计算时间、空间开销都是 O (1)千万级别迭代也不会占用大量内存。四、封装对外的 range 函数模板现在底层的detail_range::impl已经就绪我们对外提供友好的函数重载给使用者调用。提供 3 种调用形式range(end)从 0 开始步长 1range(begin, end)自定义起点终点步长默认为 1range(begin, end, step)自定义起点终点和步长重点注意第三个重载起点、步长可以是不同类型比如range(2,8,0.5)整型 浮点。需要用decltype(begin step)自动推导最终返回值类型使用后置返回类型语法。// [0, end), step 1templatetypenameTdetail_range::implTrange(T end){return{T{},end,1};}// [begin, end), step 1templatetypenameTdetail_range::implTrange(T begin,T end){return{begin,end,1};}// [begin, end), custom steptemplatetypenameT,typenameUautorange(T begin,T end,U step)-detail_range::impldecltype(beginstep){usingr_tdetail_range::impldecltype(beginstep);returnr_t(begin,end,step);}五、完整测试体验效果写测试函数测试整数、负数、浮点数、字符多种场景#includeiostream#includestdexcept// 把上面 iterator、impl、range函数全部放这里voidtest_range(){std::coutrange(15): ;for(autoi:range(15)){std::couti ;}std::coutn;std::coutrange(2,6): ;for(autoi:range(2,6)){std::couti ;}std::coutn;std::coutrange(2,6,3): ;for(autoi:range(2,6,3)){std::couti ;}std::coutn;std::coutrange(-2,-6,-3): ;for(autoi:range(-2,-6,-3)){std::couti ;}std::coutn;std::coutrange(10.5,15.5): ;for(autoi:range(10.5,15.5)){std::couti ;}std::coutn;std::coutrange(35,27,-1): ;for(autoi:range(35,27,-1)){std::couti ;}std::coutn;std::coutrange(2,8,0.5): ;for(autoi:range(2,8,0.5)){std::couti ;}std::coutn;std::coutrange(8,7,-0.1): ;for(autoi:range(8,7,-0.1)){std::couti ;}std::coutn;std::coutrange(a,z): ;for(autoch:range(a,z)){std::coutch;}std::coutn;}intmain(){test_range();return0;}运行输出节选range(15): 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 range(2,6): 2 3 4 5 range(2,6,3): 2 5 range(-2,-6,-3): -2 -5 range(a,z): abcdefghijklmnopqrstuvwxy可以看到正数、反向负数、浮点步长、字符迭代全部正常工作✅。⚠️小提示浮点数迭代会存在浮点数精度误差业务场景需要留意。六、总结 拓展思考基于范围的 for 循环不是魔法只是语法糖。编译器依赖begin()、end()获取迭代器只要自定义类型提供对应的迭代器接口就能使用这个语法。迭代器不一定需要持有全部数据像我们实现的 range 就是惰性迭代边迭代边计算内存开销极小。迭代结束判断优先使用计数器 cursor不要直接拿业务值做不等对比否则步长无法整除时会出现死循环。注意合法性校验正向迭代终点必须大于起点反向迭代终点要小于起点非法入参要做防护。拓展思考C20 标准引入了 Ranges 库原生支持类似 range 的视图性能更强接口更丰富。如果你的项目可以升级 C20可以优先使用标准 Ranges。但手动实现一遍这个小轮子能够极大加深你对迭代器、基于范围 for 循环底层原理的理解对阅读 STL 源码非常有帮助。本篇代码基于 C11 标准编译GCC 编译命令参考g main.cpp -stdc11 -o range_demo。

相关新闻

2026/8/31 4:57:50

《易学・益䷩|道影子新解 042》

摘要益卦(䷩)承接损卦 “损而有孚、损极而益” 之后,揭示当系统损上益下、增益下方、施惠于民时,便进入 “风雷益、损上益下” 的增益力场。其本质是风雷相助、损上益下,下震上巽,雷动于下、风散于上&#…

2026/8/31 4:57:50

【计算机毕业设计】基于SpringBoot的社区团购平台

基于SpringBoot的社区团购平台 一、项目简介 社区团购平台是一套面向社区居民的前后端分离拼团购物系统。后端采用 Spring Boot、MyBatis、MySQL 和 Token 鉴权,前端采用 Vue;系统将商品分类、商品展示、团购活动、购物车、收货地址、订单和平台公告整…

2026/8/31 4:57:50

《易学・损䷨|道影子新解 041》

摘要损卦(䷨)承接解卦 “险难解除、恢复重建” 之后,揭示当系统需要减损、节制、自我克制时,便进入 “损下益上、损己利人” 的损减力场。其本质是山下有泽、损下益上,下兑上艮,泽水向下渗透、山体向上增益…

2026/8/31 5:07:51

大规模MIMO信道估计的MATLAB仿真:LS、OMP、MOMP与CoSaMP算法对比指南

大规模MIMO通信系统的信道估计,在MATLAB里跑性能仿真,核心任务就是在导频数量少于天线数量、信道矩阵维度非常大的前提下,比较不同估计算法恢复信道的能力。标题里出现的LS、OMP、MOMP、CoSaMP,正好覆盖了四类有代表性的方法&…

2026/8/31 5:07:51

在 KVM 虚拟化中启用 UEFI 支持

什么是BIOS? 计算机启动时会加载 BIOS,以初始化和测试硬件功能。它使用 POST 或 Power On Self Test 来确保硬件配置有效且工作正常,然后寻找存储引导设备的 MBR(Master Boot Records),并使用它来启动引导…

2026/8/31 5:07:51

后端技术面试全流程复盘:从项目深挖到系统设计实战

不少朋友私信问最近面试的情况,我就把今天这场完整复盘一下。这次面的是某互联网公司的后端开发岗,整体面下来节奏紧凑,一面技术、二面系统设计、三面HR,总共三轮连轴转。面完最大的感受是:现在面试越来越不看“背了多…

2026/8/31 5:07:50

飞鱼视频采集器 - 网页嗅探功能操作手册

飞鱼视频采集器 - 网页视频嗅探技术完全指南:HLS、Blob、DASH 分离流的捕获原理与操作方法技术分享声明 本文为纯技术原理与操作方法分享,介绍基于 Chromium 的浏览器视频资源识别技术。文中提到的任何演示工具、浏览器、网站名称仅用于说明技术实现思路…

2026/8/31 5:02:50

全向轮小车源码深度拆解:从运动学解算到PID闭环控制

简介:本资源是一套基于STM32的全向轮小车嵌入式控制源码,面向嵌入式初学者、机器人方向课程设计者及智能小车开发爱好者,解决多自由度运动控制、IMU姿态解算与多协议外设协同驱动等典型工程问题。压缩包共162个文件,含29个头文件&…

2026/8/31 1:05:20

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/31 2:14:20

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/31 1:41:28

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/31 0:07:32

STM32C5设备支持包(IAR DFP)安装指南与常见坑

上一阵子在IAR里折腾一块基于STM32C5系列的新板子,工程从STM32CubeMX导出来之后怎么都编译不过。报错信息很干脆:找不到设备描述文件。跟着错误路径去查,发现指向的是一个让我愣了一下的名字:STMicroelectronics.stm32c5xx.2.1.0.…

2026/8/31 0:07:32

STM32N657 SWO引脚矛盾:CubeMX显示PB3,数据手册为PB5

拿到STM32N657这颗料的第一天,我就撞上了一个让人原地懵圈的引脚矛盾:CubeMX里清清楚楚显示SWO在PB3,翻开数据手册的引脚说明表,却赫然写着PB5。对于一个靠SWO输出调试日志吃饭的人而言,这种"工具和手册打架"…

2026/8/28 16:16:48

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/28 16:16:50

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/28 11:06:45

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…