std::chrono 是跨平台高精度计时唯一推荐方案,首选 steady_clock;需正确封装 timer 类(禁拷贝、允移动、默认构造初始化、提供 restart);定时任务用 sleep_for + 线程,避免轮询或平台 api;queryperformancecounter 通常无需手动调用。

用 std::chrono 做高精度计时,别碰 clock() 和 time()
Windows/Linux/macOS 上都可用、精度高、类型安全——std::chrono 是唯一推荐的起点。老式 clock() 在 Windows 下是 CPU 时间,Linux 下行为不一致;time() 只到秒级,完全没法做“计时器”。
-
std::chrono::steady_clock是首选:单调递增、不受系统时间调整影响,适合测量耗时 - 避免用
system_clock做计时器主体,它可能被 NTP 调整跳变 - 构造时直接记录起始点:
auto start = std::chrono::steady_clock::now(); - 计算差值用
duration_cast,比如转毫秒:std::chrono::duration_cast<:chrono::milliseconds>(end - start).count()</:chrono::milliseconds>
封装一个可重置的 Timer 类,关键在移动语义和默认构造
很多人写完发现对象一拷贝就乱计时,或者无法重复使用——问题出在没管好内部时间点的生命周期。
- 内部只存
std::chrono::time_point,不存duration;每次调用elapsed()才实时计算 - 提供
restart()方法:重新赋值start_ = steady_clock::now(),比析构+重建更轻量 - 默认构造函数必须初始化
start_,否则未定义行为;建议设为steady_clock::now()或抛异常(看场景) - 禁用拷贝(
= delete),但允许移动:移动后原对象应进入有效但未启动状态(例如start_设为 epoch)
定时回调?别自己轮询,用 std::thread + std::this_thread::sleep_for 最简可行
没有跨平台原生“定时器线程”,强行用信号或平台 API(如 Windows SetTimer)反而难维护、易出错。
- 单次延迟执行:启动新线程,
sleep_for后调用回调,然后线程退出 - 周期性任务:循环中
sleep_for,每次醒来检查是否超时/是否需停止(用std::atomic<bool></bool>控制) - 注意
sleep_for不保证精确唤醒,实际延迟 ≥ 指定值;要求高精度请用 busy-wait +now()校验(但耗 CPU) - 别把
Timer对象传进线程里还同时在主线程读写——加std::mutex或改用原子变量同步状态
Windows 下 QueryPerformanceCounter 还有必要吗?基本不用
除非你在写游戏引擎底层、高频采样硬件事件,或需要纳秒级抖动控制——否则 std::chrono::steady_clock 在现代编译器(MSVC 2015+/Clang 6+/GCC 5+)下已直接映射到 QueryPerformanceCounter,无需手动封装。
立即学习“C++免费学习笔记(深入)”;
- 自己调
QueryPerformanceCounter容易漏掉频率换算、溢出处理、多核 TSC 不一致等问题 - MinGW 等非 MSVC 工具链可能 fallback 到
GetTickCount64,但std::chrono会自动适配,你不用操心 - 唯一例外:你需要和某段旧 C 代码共享同一套计时逻辑,且对方强依赖
LARGE_INTEGER——这时才考虑封装一层薄胶水
真正容易被忽略的是时钟稳定性:即使用了 steady_clock,如果系统处于省电模式(尤其是笔记本插电/拔电切换)、CPU 频率动态缩放剧烈,实测间隔仍可能漂移。需要亚毫秒级稳定性的场景,得关睿频、锁 CPU 频率,或者换硬件定时器方案。









