從一個“詭異“的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
英文地址,請注明出處:http://en.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;減少內存分配和…