[原创](Modern C++)现代C++的关键性概念: 非常独特的std::sentinel_for概念(哨兵概念)

作者

常用网名: 猪头三

出生日期: 1981.XX.XX

企鹅交流: 643439947

个人网站: 80x86汇编小站

编程生涯: 2001年~至今共24年

职业生涯: 22年

开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、

开发工具: Visual Studio、Delphi、XCode、C++ Builder、Eclipse

技能种类: 逆向 驱动 磁盘 文件 大数据分析

涉及领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全

项目经历: 股票模型量化/磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测

专注研究: 机器学习、股票模型量化、金融分析

序言

在C++20中, 范围库为带来了更加灵活和高效的数据处理方式, 而std::sentinel_for概念正是其中一个重要且独特的创新点. 传统的迭代器对(即begin和end迭代器)需要同时给定起始位置和结束位置, 在某些场景下显得不够灵活, 尤其是在迭代的结束条件并非固定位置, 而是由某个动态条件决定时. 例如, 可能希望在遇到特定值(如换行符\n)时停止迭代, 而不是遍历整个容器. 在这种情况下, C++20的std::sentinel_for概念(即哨兵概念), 提供了一种全新的解决方案.

哨兵的特性

哨兵(Sentinel)是一个与迭代器搭配使用的特殊对象, 它的作用是定义迭代的终止条件. 与传统固定的end迭代器不同, 哨兵允许根据实际需求自定义结束逻辑, 从而极大地增强了迭代器的表达能力.

代码演示

cpp 复制代码
#include <iostream>
#include <ranges>
#include <io.h>
#include <fcntl.h>

// 哨兵类: 用于判断迭代是否满足结束条件
template<class Iter>
class Sentinel {
public:
    using value_type = std::iter_value_t<Iter>;

    // 构造函数: 指定结束值
    Sentinel(value_type param_end_value) : mpr_iv_End{param_end_value} {}
    // 默认构造函数: 初始化为0
    Sentinel() : mpr_iv_End{0} {}

    // 定义比较运算符 == 和 !=, 支持两种参数顺序
    friend bool operator==(const Iter& param_it, const Sentinel& param_s) {
        return *param_it == param_s.mpr_iv_End;
    }
    friend bool operator==(const Sentinel& param_s, const Iter& param_it) {
        return *param_it == param_s.mpr_iv_End;
    }
    friend bool operator!=(const Iter& param_it, const Sentinel& param_s) {
        return !(*param_it == param_s.mpr_iv_End);
    }
    friend bool operator!=(const Sentinel& param_s, const Iter& param_it) {
        return !(*param_it == param_s.mpr_iv_End);
    }

private:
    value_type mpr_iv_End; // 存储结束条件值
};

int main() {
    // 设置输出模式为宽字符
    _setmode(_fileno(stdout), _O_WTEXT);

    // 示例: 使用哨兵确定迭代范围, 结束条件为遇到第一个'\n'
    // 预期输出: Hello, World!
    const wchar_t wchar_Demo[] = L"Hello, World!\nBye for now\n";
    std::ranges::for_each(wchar_Demo, Sentinel<const wchar_t*>(L'\n'), 
        [](const wchar_t param_Input) {
            std::wcout << param_Input;
        });

    std::cin.get(); // 暂停以查看输出
    return 0;
}

代码说明

在这段代码中, 实现了一个基于哨兵的迭代控制机制, 具体说明如下:

  1. 哨兵类的定义:

*****定义了一个模板类Sentinel<Iter>, 其中Iter是迭代器的类型. 通过std::iter_value_t<Iter>推导出迭代器指向的元素类型value_type.

*****哨兵类持有一个私有成员mpr_iv_End, 用于存储结束条件的值(如示例中的\n). 构造函数允许用户传入自定义的结束值, 默认构造函数则将其初始化为0.

*****通过友元函数operator==和operator!=, 定义了迭代器与哨兵之间的比较逻辑. 当迭代器指向的元素等于mpr_iv_End时, 迭代停止.

  1. 主函数中的使用:

*****定义了一个宽字符数组wchar_Demo, 内容为"Hello, World!\nBye for now\n". 目标是只输出第一行(即遇到第一个\n时停止).

*****使用C++20的std::ranges::for_each, 传入起始迭代器wchar_Demo(指向数组开头)和哨兵Sentinel<const wchar_t*>(L'\n'). 第三个参数是一个lambda函数, 用于输出当前字符.

*****当迭代器遇到\n时, operator==返回true, std::ranges::for_each停止迭代, 最终输出"Hello, World!"

  1. 运行机制:

*****std::ranges::for_each会从wchar_Demo开始逐个访问元素, 并与哨兵进行比较. 当迭代器指向的字符等于哨兵中的\n时, 迭代终止. 这种机制使得无需显式指定结束迭代器, 而是通过动态条件控制范围.

总结

std::sentinel_for概念是现代C++中一项创新且强大的特性, 它扩展了传统迭代器模型的局限性. 通过哨兵, 可以轻松定义自定义的迭代结束条件. 在运行时动态决定结束条件, 处理流式数据、不定长输入或复杂逻辑时尤为有用. 此外, C++20的ranges库与哨兵概念无缝集成, 进一步提升了代码的可读性和通用性.

相关推荐
Chester_19993 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
EXI-小洲4 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
会周易的程序员4 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
机器视觉知识推荐、就业指导4 小时前
为什么老说“纯 Qt 没啥就业市场”?
开发语言·qt
telepan4 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?
开发语言·qt
小灰灰搞电子5 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
QT界面美化性能优化5 小时前
QT+AI:使用AI技术为QT应用程序赋能
c++·人工智能·qt·opencv·qt教程·qt6.3
m0_695251495 小时前
Qt MaintenanceTool 使用国内镜像加速下载(超详细教程)
开发语言·qt
大衛說6 小时前
《Python 从入门到精通》系列总览与学习路线
开发语言·python·学习
学习星球7 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode