C++开发基础之简单的计时器也有适配场景
一、前言
计时器的开发通常涉及到计算时间间隔的方法和计算时间的方式。一般计时器的开发步骤:
-
获取起始时间点:在开始计时时,记录当前的时间戳作为起始时间点。
-
获取结束时间点:在结束计时时,记录当前的时间戳作为结束时间点。
-
计算时间间隔:通过起始时间点和结束时间点的差值,计算出经过的时间间隔。
-
显示计时结果:将计算得到的时间间隔转换成合适的时间单位(如毫秒、秒等),并展示给用户。
二、计时器的适配场景
下面是对比各种方法实现计时器功能的优劣势、适用场景、精度、易用性和平台兼容性的表格:
| 方法 | 优势 | 劣势 | 适用场景 | 精度 | 易用性 | 平台兼容性 |
|---|---|---|---|---|---|---|
<chrono> | 高精度、跨平台 | 需要 C++11 及以上标准支持 | 跨平台应用、需要高精度计时的场景 | 高 | 中 | 良好 |
| 标准库函数 | 简单易用 | 精度可能不够高 | 简单计时需求、不需要太高精度的场景 | 低 - 中 | 高 | 良好 |
| 系统特定函数 | 高精度、系统调用简单 | 可移植性差 | 特定平台上需要更高精度的计时需求 | 高 | 中 | 差 |
| 第三方库 | 功能丰富、可扩展性强 | 引入外部依赖 | 复杂计时需求、需要定制化计时功能的场景 | 高 | 高 | 良好 |
| 硬件计时器 | 高精度、硬件支持 | 硬件依赖性强 | 对计时精度要求极高的场景 | 非常高 | 中 | 依赖硬件 |
三、基于标准库实现
3.1 使用clock函数
使用 clock() 函数实现计时器功能。
- 记录开始时间:在需要开始计时的地方调用
clock()函数,将其返回值保存为开始时间。 - 记录结束时间:在需要结束计时的地方再次调用
clock()函数,将其返回值保存为结束时间。 - 计算时间间隔:将结束时间减去开始时间,然后除以
CLOCKS_PER_SEC来获取经过的时间(以秒为单位)。
#include <iostream>
#include <ctime>int main() {clock_t start, end;double cpu_time_used;start = clock(); // 记录开始时间// 进行需要计时的操作for (int i = 0; i < 1000000; ++i) {// do something}end = clock(); // 记录结束时间cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; // 计算时间间隔std::cout << "CPU time used: " << cpu_time_used << " seconds" << std::endl;return 0;
}
在这个示例中,首先记录了开始时间和结束时间,然后计算了经过的时间间隔。
请注意,由于 clock() 函数返回的是 CPU 时钟周期数,所以需要将其转换为秒数才能得到实际的时间间隔。
3.2 使用time函数
使用 time() 函数实现计时器相对简单,但其精度可能不足以满足高精度计时的需求。
#include <iostream>
#include <ctime>int main() {time_t start, end;double time_used;start = time(NULL); // 记录开始时间// 进行需要计时的操作for (int i = 0; i < 1000000; ++i) {// do something}end = time(NULL); // 记录结束时间time_used = difftime(end, start); // 计算时间间隔std::cout << "Time used: " << time_used << " seconds" << std::endl;return 0;
}
在这个示例中,我们使用 time() 函数获取当前时间的秒数作为开始时间和结束时间,并通过 difftime() 函数计算时间间隔。
请注意,time() 函数返回的时间精度通常是秒级别,因此不适合需要高精度计时的场景。如果需要更高精度的计时功能,建议使用其他方法,如 <chrono> 头文件中的函数。
四、基于chrono库实现
使用<chrono>头文件中的功能来实现计时功能:
#include <iostream>
#include <chrono>class Timer {
public:void start() {startTime = std::chrono::high_resolution_clock::now();}void stop() {endTime = std::chrono::high_resolution_clock::now();}void displayDuration(const std::string& message) {auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);std::cout << message << ": " << duration.count() << " ms" << std::endl;}
private:std::chrono::time_point<std::chrono::high_resolution_clock> startTime, endTime;
};
int main() {Timer timer;timer.start();// 模拟一些操作for (int i = 0; i < 1000000; ++i) {// do something}timer.stop();timer.displayDuration("Elapsed time");return 0;
}
在这个示例中,Timer类封装了计时器的功能。start()方法开始计时,stop()方法停止计时,displayDuration()方法用于显示经过的时间。
在main()函数中,创建一个Timer对象,调用start()开始计时,在模拟的操作后调用stop()停止计时,并调用displayDuration()方法显示经过的时间。
五、基于系统特定函数
5.1 QueryPerformanceCounter
可以使用Windows系统提供的QueryPerformanceCounter()函数来实现简单计时器功能:
#include <iostream>
#include <Windows.h>class Timer {
public:void start() {QueryPerformanceFrequency(&frequency);QueryPerformanceCounter(&startCounter);}void stop() {QueryPerformanceCounter(&endCounter);}void displayDuration(const std::string& message) {LARGE_INTEGER elapsedTime;elapsedTime.QuadPart = endCounter.QuadPart - startCounter.QuadPart;double duration = static_cast<double>(elapsedTime.QuadPart) / frequency.QuadPart;std::cout << message << ": " << duration << " seconds" << std::endl;}private:LARGE_INTEGER frequency;LARGE_INTEGER startCounter, endCounter;
};int main() {Timer timer;timer.start();// 模拟一些操作for (int i = 0; i < 1000000; ++i) {// do something}timer.stop();timer.displayDuration("Elapsed time");return 0;
}
在这个示例中,Timer类使用QueryPerformanceCounter()函数来获取高精度的计时。start()方法开始计时,stop()方法停止计时,displayDuration()方法用于显示经过的时间。
在main()函数中,创建一个Timer对象,调用start()开始计时,在模拟的操作后调用stop()停止计时,并调用displayDuration()方法显示经过的时间。
5.2 GetTickCount64
GetTickCount64函数是Windows API中用于获取系统启动后经过的毫秒数的函数,它可以用来实现简单的计时器功能。
#include <iostream>
#include <Windows.h>class Timer {
public:void start() {startTime = GetTickCount64();}void stop() {endTime = GetTickCount64();}void displayDuration(const std::string& message) {DWORD duration = endTime - startTime;std::cout << message << ": " << duration << " ms" << std::endl;}private:ULONGLONG startTime, endTime;
};int main() {Timer timer;timer.start();// 模拟一些操作for (int i = 0; i < 1000000; ++i) {// do something}timer.stop();timer.displayDuration("Elapsed time");return 0;
}
在这个示例中,Timer类使用GetTickCount64函数来获取系统启动后的毫秒数。start()方法开始计时,stop()方法停止计时,displayDuration()方法用于显示经过的时间。
在main()函数中,创建一个Timer对象,调用start()开始计时,在模拟的操作后调用stop()停止计时,并调用displayDuration()方法显示经过的时间。
六、基于第三方库实现
使用C++中的高精度计时器库ChronoLib来实现计时器功能:
#include <iostream>
#include "ChronoLib.h"int main() {Chrono::high_resolution_timer timer;double elapsed_time = 0.0;// 计时开始timer.start();// 执行需要计时的操作// ...// 计时结束elapsed_time = timer.elapsed();// 输出计时结果std::cout << "Elapsed Time: " << elapsed_time << " seconds" << std::endl;return 0;
}
在这个示例中,我们使用ChronoLib库中的high_resolution_timer类来实现高精度计时器功能。我们创建了一个计时器对象timer和一个变量elapsed_time来保存计时结果。在需要计时的操作执行前,我们通过start函数开始计时。在需要计时的操作执行完成后,我们使用elapsed函数来获取计时结果,并将结果保存到elapsed_time变量中。最后,我们输出计时结果。
七、基于硬件计时器模块实现
硬件计时器通常指的是计算机或嵌入式系统中的专用计时器硬件模块,这些模块通常由硬件设计师设计并集成到处理器或主板中。硬件计时器具有高精度、稳定性和可靠性的特点,通常用于需要精确时间测量和控制的应用场景。
八、总结
每种方法都有其独特的优势和劣势,具体选择取决于项目需求、平台要求和精度要求。
相关文章:
C++开发基础之简单的计时器也有适配场景
一、前言 计时器的开发通常涉及到计算时间间隔的方法和计算时间的方式。一般计时器的开发步骤: 获取起始时间点:在开始计时时,记录当前的时间戳作为起始时间点。 获取结束时间点:在结束计时时,记录当前的时间戳作为结…...
数电学习笔记——逻辑函数及其描述方法
目录 一、逻辑函数 二、逻辑函数的描述方法 1、逻辑真值表 2、逻辑函数式 3、逻辑图 4、波形图 三、逻辑函数的两种标准形式 1、最小项与最大项 最小项 最小项的性质 最大项 最大项的性质 2、最大项与最小项的关系 3、逻辑函数的最小项之和形式 4、逻辑函数的最…...
2024年护眼台灯哪家品牌好?五款优质品牌专业推荐
护眼台灯几乎是每个孩子书桌上都会有的灯具,但还是有不少家长觉得是“智商税”。其实护眼台灯好处非常多,列如能够提供舒适的照明,缓解用眼疲劳,预防近视等等。所以今天准备了一期护眼台灯测评,并附上护眼台灯的榜单&a…...
搜索iconfont或者阿里图标就可以得到免费的图标
你在搜索过程中就会出现一些无耻,不要脸的网站,比如说下面这个 这个才是阿里图标 看它的网址 都是免费的...
android实战视频教程,细数Android开发者的艰辛历程
缘起 随着互联网企业的不断发展,产品项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑、快速迭代的目的越来越难,还有应用之间的互相调用等等问题,插件化技术应用而生。如果没有插件化技术,美…...
nav2_gps_waypoint_follower_demo 不能在ros2 humble中直接使用的解决方法
GIT上的nav2_gps_waypoint_follower_demo是基于ros-iron编写的,其中followGpsWaypoints(wps) service只能在Iron上使用。 解决方法: 第一步:将interactive_waypoint_follower.py修改为如下代码: import rclpy from rclpy.node …...
华为OD机试 - 螺旋数字矩阵
1 题目描述 疫情期间,小明隔离在家,百无聊赖,在纸上写数字玩。他发明了一种写法: 给出数字个数 n (0 < n ≤ 999)和行数 m(0 < m ≤ 999),从左上角的 1 开始&…...
Vue响应式内容丢失处理
对数组和对象进行不当的修改会使Vue的对象丢失响应式,这时可以直接console.log丢失的对象,看是否有getter和setter 对于数组和对象,只有使用 Vue 提供的一些方法(如 push()、pop()、splice()、set() 等)进行修改才会触…...
Linux安装Rabbitmq
说明:本文章主要是rabbitmq在Linux系统上的安装,文章中包含了rabbitmq的下载及依赖下载 1.版本选取,这里的选取主要是版本的兼容问题 去这个网址查看mq和erlang版本兼容:RabbitMQ Erlang Version Requirements | RabbitMQ 2.相…...
在nginx 服务器部署vue项目
以人人快速开发的开源项目:renren-fast-vue 为例 注:这里开始认为各位都会使用nginx 打包vue项目 npm run build 测试打包的项目是否可以运行 serve dist 可以正常运行 编译报错请移步到:renren-fast-vue1.2.2 项目编译报错: build g…...
制作一个简单的HTML个人网页
制作一个简单的HTML个人网页 1.1 硬件1.1.1 一台电脑1.1.2 配置要求 1.2 系统1.3 软件 二、制作一个简单的HTML个人网页1.创建一个HTML网页1.1 新建文本文档1.2 另存文本文档1.3 命名为index.html 2.编写HTML代码2.1 打开HTML2.2 复制HTML代码2.3 粘贴HTML代码2.4 保存HTML 3.预…...
HM2019创建载荷工况
该案例中将介绍载荷、工况、约束的创建 步骤一:首先创建两个载荷集(Load Collector)用来存放载荷和约束 步骤二:在Analysis面板下创建约束(Analysis→constraints) 注意:Load type选择SPC表示统计过程控制(Statistical Process Control) 步…...
Effective C++ 学习笔记 条款14 在资源管理类中小心copying行为
条款13导入这样的观念:“资源取得时机便是初始化时机”(Resource Acquisition Is Initialization,RAII),并以此作为“资源管理类”的脊柱,也描述了auto_ptr和tr1::shared_ptr如何将这个观念表现在heap-base…...
c++数据结构算法复习基础-- 3 --线性表-单向链表-笔试面试常见问题
1、单链表逆序 思路图 代码实现 //著: 链表结构里记得加 friend void ReverseLink(Clink& link); void ReverseLink(Clink& link) {Node* p link.head_->next_;while( p nullptr){return;}Node* q p->next_;link.head_->next_ nullptr;while(p ! nullpt…...
【踩坑专栏】追根溯源,从Linux磁盘爆满排查故障:mycat2与navicat不兼容导致日志暴增
昨天遇到了一个比较奇怪的问题,就是在挂起虚拟机的时候,虚拟机提示我XX脚本正在运行,很奇怪,我没有运行脚本,为什么会提示我这个呢。今天恢复虚拟机,也提示了一下脚本的问题,而且发现Linux明显异…...
DolphinScheduler——奇富科技的调度实践
目录 一、技术架构 二、业务挑战 2.1 调度任务量大 2.2 运维复杂 2.3 SLA要求高 三、调度优化实践 3.1 重复调度 3.2 漏调度 3.3 Worker服务卡死 3.4 任务重复运行 四、服务监控 4.1 方法耗时监控 4.2 任务调度链路监控 五、用户收益 原文大佬的这篇调度系统案例…...
2024年最全洗地机选购攻略盘点丨希亦、小米、云鲸、海尔洗地机哪款值得入手?
在现代家居清洁中,洗地机是不可或缺的得力助手,它融合了吸尘、拖地等多种功能。面对市场上琳琅满目的洗地机品牌和型号,选择一个可靠的品牌至关重要。优质的品牌能够提供高品质的产品,使您的清洁工作更加轻松高效。本文将向您推荐…...
HTML笔记3
21,label标签 <label for"...">...</label> <label>...</label> <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content&qu…...
利用Python副业赚钱,看完这篇你就懂了!
Python都可以做哪些副业? 1、兼职处理数据Excel整理数据功能虽然很强大,但在Python面前,曾经统治职场的它也的败下阵来。因为Python在搜集数据整理分析数据的过程中更加便捷,通过几行代码还可以实现自动化操作。 如果你学会Pyth…...
FP16(半精度浮点数)、FP32(单精度浮点数)和INT8
在深度学习和计算机视觉领域中,FP16(半精度浮点数)、FP32(单精度浮点数)和INT8(8 位整数)是常见的数据类型或精度表示方式。它们在不同的场景下有各自的优势和用途。 FP16(半精度浮…...
Pixel Couplet Gen入门必看:Streamlit Components封装像素春联React组件
Pixel Couplet Gen入门必看:Streamlit Components封装像素春联React组件 1. 项目介绍 Pixel Couplet Gen是一款基于ModelScope大模型驱动的创意春联生成器。与传统春联设计不同,它采用了独特的8-bit像素游戏风格,将中国传统春节元素与复古电…...
伯克利Octo机器人框架实战:5步搞定跨平台任务迁移(附代码)
伯克利Octo机器人框架实战:5步搞定跨平台任务迁移(附代码) 在机器人开发领域,硬件平台的多样性一直是阻碍算法快速部署的主要瓶颈。想象一下,你花费数月为WidowX机械臂开发的抓取算法,当实验室新购入UR5工业…...
让 AI 听懂业务、直接干活:销售易 NeoAgent 2.0 的三大跃迁
当软件行业仍在争论“AI是否会杀死SaaS”时,销售易已经给出了自己的答案。3月27日,在2026腾讯云城市峰会首站上海站,腾讯旗下CRM销售易正式发布新一代营销服全场景AI原生CRM——NeoAgent 2.0。这并非一次简单的产品迭代,而是销售易…...
高频电路布线十大实用技巧与EMC解决方案
1. 高频电路布线的基本概念与挑战高频电路通常指工作频率达到或超过45MHz~50MHz的数字逻辑电路,当这类电路占整个电子系统1/3以上比重时,就必须考虑高频特性带来的设计挑战。我在实际项目中多次遇到这样的场景:一个原本在低频下工作良好的电路…...
Anubi基金会为何押注Cassava?深度解析Web3数据层+社交任务的黄金组合
Anubi基金会战略投资Cassava:Web3社交任务与数据层的价值重构 当Web3世界从DeFi的金融实验转向更广泛的社会化应用时,基础设施的演进正在经历一场静默的革命。Anubi基金会近期对Cassava Network的战略投资,揭示了两个关键趋势:社交…...
如何快速解锁网易云音乐NCM文件:ncmdumpGUI终极指南
如何快速解锁网易云音乐NCM文件:ncmdumpGUI终极指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 还在为网易云音乐下载的NCM格式文件无法在其他…...
实战应用:为团队部署即装即用的中文版mobaxterm统一环境
在团队协作开发中,统一开发环境配置是个常见痛点。最近我们团队就遇到了这个问题:新成员加入时,每个人都要手动配置MobaXterm的中文界面、服务器连接、工具集等,既费时又容易出错。经过实践摸索,我总结出一套用脚本自动…...
3步打造个人数据备份系统:QQ空间数字记忆永久保存指南
3步打造个人数据备份系统:QQ空间数字记忆永久保存指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字化时代,个人数据备份已成为保护数字记忆的关键措施。…...
技术赋能B端拓客:号码核验行业的迭代升级与价值深耕,
在数字经济持续深耕的当下,B端市场的竞争逻辑已发生根本性转变,“粗放拓客”逐渐被“精准高效”取代,企业对拓客全流程的效率与成本管控提出了更高要求。号码核验作为B端拓客的前置核心环节,其作用远不止于简单的空号筛查…...
2026年的具身智能:不再“讲故事”,而是拼“分数”?
作者:刘致呈编辑:Evin审核:徐徐出品:互联网江湖最近,具身智能行业发生了两件大事:一是行业标杆——宇树科技要IPO了。二是中国信息通信研究院联合40余家单位共同起草的具身智能领域首个行业标准,正式发布了…...
