从一个“诡异“的C++程序理解状态机、防抖与系统交互

引言

在编程世界中,有时一个看似简单的代码片段可能隐藏着令人惊讶的复杂性。本文将从一个"故意设计"的C++程序出发,深入探讨其背后涉及的状态机模式、防抖机制以及操作系统与控制台的交互原理。通过这个案例,我们不仅能理解这些核心概念,还能掌握一种探索性编程的思维方式。

一、诡异的程序:循环10次却只输出0-4?

让我们先来看看这个引发讨论的C++程序:

#include<iostream>
#include<windows.h>
class Smart {bool timesExist;int n;void timeHandle(int time) {timesExist = true;std::cout << n << std::endl;Sleep(time);n++;}
public:Smart(): timesExist(false), n(0) {}~Smart() {}void handle(int time) {if (timesExist) {timesExist = false;} else {timeHandle(time);}}
};
int main() {Smart s;for (int i = 0; i < 10; i++) {s.handle(1000);}return 0;
}

现象描述
当我们运行这个程序时,预期会看到0-9的数字每秒输出一个,但实际结果却是每隔一秒输出一个数字,最终只显示0-4,总共5个数字。为什么会这样?

二、状态机模式解析

这个程序的核心在于通过timesExist布尔变量实现了一个简单的双态状态机

  1. 初始状态timesExist = false

    • 首次调用handle()时,执行timeHandle()
    • 输出当前值n,调用Sleep(1000),然后n++
    • 设置timesExist = true
  2. 暂停状态timesExist = true

    • 再次调用handle()时,直接执行timesExist = false
    • 不输出任何内容,也不调用Sleep()
  3. 状态转换
    每次调用handle()都会在这两个状态之间切换,导致每两次调用中只有一次输出

执行流程图

初始态[timesExist=false] → 调用handle() → 输出n → Sleep(1000) → n++ → 设置timesExist=true →再次调用handle() → 重置timesExist=false → 无输出 → 循环

关键结论

  • 循环10次实际上只触发了5次输出(第1、3、5、7、9次调用)
  • Sleep(1000)只在输出时执行,导致每次输出间隔约2秒(而非预期的1秒)
三、与JavaScript防抖机制的对比

有读者指出这个程序与前端的**防抖(Debounce)**机制有微妙的相似性。让我们来对比分析:

  1. 防抖机制核心逻辑(JavaScript实现)

    function debounce(func, delay) {let timer;return () => {clearTimeout(timer); // 重置计时器timer = setTimeout(func, delay); // 延迟执行}
    }
    
    • 效果:在连续触发事件时,只执行最后一次调用
  2. 相似点

    • 都通过状态记录控制执行频率
    • 都可能产生"减少执行次数"的效果
  3. 本质区别

    特性你的C++程序JavaScript防抖
    控制机制状态机(布尔变量)计时器(时间窗口)
    执行时机立即执行(特定状态下)延迟执行(时间窗口结束后)
    应用场景交替执行场景(如开关控制)高频事件处理(如搜索框输入)
四、控制台输出的隐藏机制

即使理解了状态机逻辑,仍有一个问题:为什么最终只看到0-4?这里涉及到控制台输出的两个关键特性:

  1. 行缓冲机制

    • std::cout通常是行缓冲的,遇到endl或缓冲区满时才刷新
    • 在某些系统中,若程序崩溃或被中断,缓冲区内容可能不会被输出
  2. Windows控制台的特殊性

    • 控制台窗口有自己的输出缓冲区和刷新策略
    • 长时间的Sleep可能影响系统对缓冲区的管理

验证实验

  • handle()末尾添加fflush(stdout)强制刷新缓冲区
  • 将输出重定向到文件观察结果:your_program.exe > output.txt
五、编程思维的升华

这个看似简单的程序实际上教会了我们:

  1. 状态机思维

    • 用简单变量实现复杂控制逻辑
    • 状态机是理解并发、异步编程的基础
  2. 系统交互意识

    • 代码行为不仅取决于语言逻辑,还受操作系统和环境影响
    • IO操作、线程调度等底层机制可能颠覆表面预期
  3. 探索性编程方法

    • 故意制造"诡异"现象是理解系统的有效途径
    • 通过变种实验隔离问题(如移除Sleep、添加多线程)
六、延伸实验建议

如果你想进一步探索,可以尝试:

  1. 多线程竞争实验

    int main() {Smart s;std::vector<std::thread> threads;for (int i = 0; i < 10; i++) {threads.emplace_back([&s]() {s.handle(1000);});}for (auto& t : threads) t.join();return 0;
    }
    
  2. 实现真正的防抖

    class Debouncer {
    public:void call(std::function<void()> func, int delay_ms) {cancel_token = true;std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));if (cancel_token) {cancel_token = false;func();}}void cancel() { cancel_token = false; }
    private:std::atomic<bool> cancel_token{false};
    };
    
结论

从这个小小的C++程序出发,我们不仅理解了状态机和防抖的区别,还触及了系统IO、多线程编程等更深层次的概念。这正是编程的魅力所在:一个看似简单的实验,可能打开通往整个知识体系的大门。下次遇到"诡异"现象时,不妨带着好奇心深入探索,你会发现每个bug背后都藏着宝贵的学习机会。

(完)

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

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

相关文章

NAS-Bench-101: Towards Reproducible Neural Architecture Search

概述这篇题为"NAS-Bench-101: Towards Reproducible Neural Architecture Search"的论文由Chris Ying等人合作完成&#xff0c;旨在解决神经网络架构搜索(NAS)领域面临的重大挑战&#xff1a;计算资源需求高和实验难以复现的问题。论文提出了NAS-Bench-101&#xff0…

SpringBoot整合Fastexcel/EasyExcel导出Excel导出多个图片

整个工具的代码都在Gitee或者Github地址内 gitee&#xff1a;solomon-parent: 这个项目主要是总结了工作上遇到的问题以及学习一些框架用于整合例如:rabbitMq、reids、Mqtt、S3协议的文件服务器、mongodb、xxl-job、powerjob还有用Docker compose部署各类中间组件。如果大家有…

网络原理--HTTPHTTPS

目录 一、HTTP 1.1 HTTP是什么 1.2 HTTP协议的工作过程 1.3 HTTP协议格式 1.3.1 抓包工具的使用 1.3.2 抓包结果 1.4 HTTP请求 1.4.1 URL 1.4.2 认识“方法” (method) 1.4.3 认识请求“报头”(header) 1.4.4 认识请求“正文”(body) 1.5 HTTP 响应详解 1.5.1 HTTP…

『 C++ 入门到放弃 』- 哈希表

一、哈希的概念 哈希&#xff0c;也称「 散列 」是一种用来进行高效查找的数据结构&#xff0c;查找的时间复杂度平均为O(1)&#xff0c;其本质就是依赖哈希函数这个算法来将 key 和该 key 存储位置建立一个映射关系。 而因为是有着映射关系&#xff0c;所以哈希的事件复杂度为…

零售收银系统开源代码全解析:连锁门店一体化解决方案(含POS+进销存+商城)

过去10年&#xff0c;收银系统技术经历了从单机版到云服务、从单纯结算到全渠道整合的快速演进。面对连锁多门店、AI称重、智能分账、跨店库存同步等新需求&#xff0c;很多企业的现有传统saas系统已显乏力。本文将梳理收银系统关键技术指标&#xff0c;助您在系统升级时做出明…

能源高效利用如何实现?楼宇自控系统智能化监管建筑设备

随着全球能源危机日益严峻和“双碳”目标的持续推进&#xff0c;建筑领域作为能耗大户&#xff08;约占社会总能耗的40%&#xff09;&#xff0c;其节能潜力备受关注。楼宇自控系统&#xff08;Building Automation System&#xff0c;简称BAS&#xff09;作为建筑智能化的核心…

校园二手交易小程序的设计与实现

文章目录前言详细视频演示具体实现截图后端框架SpringBoot微信小程序持久层框架MyBaits成功系统案例&#xff1a;参考代码数据库源码获取前言 博主介绍:CSDN特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续…

Redis(二):Redis高级特性和应用(慢查询、Pipeline、事务)

Redis的慢查询 许多存储系统&#xff08;例如 MySQL)提供慢查询日志帮助开发和运维人员定位系统存在的慢操作。所谓慢查询日志就是系统在命令执行前后计算每条命令的执行时间&#xff0c;当超过预设阀值,就将这条命令的相关信息&#xff08;例如:发生时间&#xff0c;耗时&…

如何为你的WordPress网站选择合适的安全插件

在管理WordPress网站时&#xff0c;安全因素至关重要。由于WordPress的广泛使用&#xff0c;它也成为了黑客攻击的首要目标。为了避免潜在的安全风险&#xff0c;选择合适的安全插件至关重要。而Wordfence和iThemes&#xff0c;作为两款颇具人气的WordPress安全插件&#xff0c…

我们使用Rust开发的AI知识库应用

这段时间陆陆续续的开发了2个AI知识库应用&#xff0c;一个面向企业&#xff0c;一个面向C端用户。 飞树智库&#xff1a;一个安全高效的面向 企业的知识库平台&#xff08;https://fskb.coderbox.cn/&#xff09;。 小飞树&#xff1a;一个专注于个人知识管理的AI应用&#…

自动化测试实战篇

目录 1. 自动化实施步骤 1.1 编写web测试用例 1.2 自动化测试脚本开发 1.3 将自动化测试补充至测试报告 1. 自动化实施步骤 1.1 编写web测试用例 1.2 自动化测试脚本开发 TestDevelopment: 测试用例 - Gitee.comhttps://gitee.com/Axurea/test-development/tree/master/2…

idea 服务器Debug端口启动设置

一&#xff1a;在阿里云服务器安全组已经设置了端口授权对象&#xff1a;正确命令&#xff1a;nohup java -Xdebug -Xrunjdwp:transportdt_socket,servery,suspendn,address9998 -jar -Duser.timezoneGMT08 -Xms256m -Xmx256m /opt/projects/*/*/*-starter-1.0-SNAPSHOT.jar -…

大模型量化004

Bert P-tuning BertPET、BertP-Tuning Chain of Thought Few shot Cot Auto-COT 解决手动编写高质量CoT示例麻烦耗时的问题 Auto COT 自动思维链生成器 1.业务场景&#xff1a; 每天收到很多反馈&#xff0c;之前需要人工整理&#xff0c;找到重点&#xff0c;做判断那些需要立…

C#(基本语法)

数据类型C#是一种强类型语言&#xff0c;变量必须声明类型。基本数据类型包括整型&#xff08;int、long&#xff09;、浮点型&#xff08;float、double&#xff09;、布尔型&#xff08;bool&#xff09;、字符型&#xff08;char&#xff09;和字符串型&#xff08;string&a…

ARM-I2C软实现

开发流程引脚初始化引脚功能定义实现读操作实现写操作GD32F4软件I2C初始化void SoftI2C_init() {// 时钟配置rcu_periph_clock_enable(SCL_RCU);// 设置输出模式gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SCL_PIN);gpio_output_options_set(SCL_PORT, GPIO_O…

防水医用无人机市场报告:现状、趋势与洞察

市场规模与增长趋势在全球医疗科技快速发展的当下&#xff0c;防水医用无人机市场正崭露头角&#xff0c;展现出强劲的发展势头。据 QYR统计&#xff0c;2023 年全球医用无人机市场销售额达到 1.9 亿美元&#xff0c;预计到 2030 年将飙升至 8.5 亿美元&#xff0c;年复合增长率…

haproxy代理

一.负载均衡 1.1.什么是负载均衡 负载均衡&#xff1a;Load Balance&#xff0c;简称LB&#xff0c;是一种服务或基于硬件设备等实现的高可用反向代理技术&#xff0c;负载均 衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备&#xff0c;…

【面试】软件测试面试题

1. 测试用例如何编写 2. bug的生命周期 项目有多少人&#xff1f;多少条测试用例&#xff1f;多少bug&#xff1f;自己发现的第一条&#xff1f;&#xff08;是不是bug&#xff09; 3. 缺陷管理工具 包括Jira, PingCode, 禅道&#xff0c;BugZilla&#xff0c;Redmine, TAPD&am…

HbuilderX开发小程序

1.打卡HbuilderX&#xff0c;选择文件—新建—项目2.创建项目3.在HbuilderX中运行前要确定微信开发这工具的服务端口号是打开的4.HbuilderX中点击预览可以实时预览5.在微信开发者中进行本地测试点击后自动跳转到微信开发者工具中运行项目

Netty中FastThreadLocal解读

io.netty.util.concurrent.FastThreadLocal 是 Netty 中提供的高性能线程局部存储&#xff08;Thread-Local Storage&#xff09;实现&#xff0c;位于 io.netty.util.concurrent 包。它是 Java 标准库 ThreadLocal 的替代品&#xff0c;旨在优化性能&#xff0c;减少内存分配和…