std::chrono::steady_clock 是唯一可靠的计时器,因其单调递增且不受系统时间调整影响;system_clock 易受ntp等干扰,high_resolution_clock 跨平台语义不一致。

std::chrono::steady_clock 是唯一靠谱的计时器
做性能测量、超时控制或间隔等待时,std::chrono::system_clock 会受系统时间调整影响(比如 NTP 同步、手动改时间),导致 duration 突然跳变甚至倒流;std::chrono::high_resolution_clock 在不同平台语义不一致(GCC 下常 alias 到 system_clock,MSVC 下可能 alias 到 steady_clock),不可靠。只有 std::chrono::steady_clock 保证单调递增、不受系统时间干扰。
实操建议:
- 所有需要“经过时间”的场景(如函数耗时统计、定时器、sleep_until)一律用
steady_clock - 避免用
system_clock做差值计算,除非你明确在处理“墙上时间”(比如日志打点、UTC 时间戳) - 跨线程共享时间点时,注意
steady_clock::now()调用开销极小,但不要在高频循环里反复调用——先取一次再复用
time_point 和 duration 别混着转
常见错误是把 steady_clock::time_point 直接强转成 long long,或者用 count() 得到裸数值后乱除——这忽略了时钟的 period(比如纳秒 vs 微秒)。更糟的是,有人拿 system_clock::time_point 和 steady_clock::time_point 直接相减,编译都过不了。
正确做法:
立即学习“C++免费学习笔记(深入)”;
- 用
time_point::time_since_epoch().count()只在调试或序列化时临时取整数,且必须配合time_point::clock::period理解单位 - 时间差统一用
duration_cast:比如std::chrono::duration_cast<:chrono::milliseconds>(end - start)</:chrono::milliseconds> - 避免写
(end - start).count() / 1000000—— 这假设了底层是纳秒,实际可能不是;用duration_cast才真正跨平台
wait_for 和 wait_until 的 timeout 参数容易传反
在 std::condition_variable::wait_for 或 std::mutex::try_lock_for 里,第二个参数是 duration(相对时间),不是 time_point;而 wait_until 才要传 time_point(绝对时间)。传错类型会导致编译失败,但更隐蔽的问题是:有人把 steady_clock::now() + 100ms 当作 duration 传给 wait_for,结果变成等待一个巨大整数毫秒。
典型误用与修正:
- ❌
cv.wait_for(lock, std::chrono::steady_clock::now() + 100ms)—— 编译不过,因为now() + ...是time_point - ✅
cv.wait_for(lock, 100ms)—— 正确:直接传duration - ✅
cv.wait_until(lock, std::chrono::steady_clock::now() + 100ms)—— 正确:传绝对时间点 - 注意
100ms是字面量,类型为std::chrono::milliseconds,别写成100 * 1ms(虽然能编译,但多一次隐式构造)
Windows 上 steady_clock 分辨率可能只有 15ms
在旧版 Windows(尤其是未启用 QPC 的系统),steady_clock::now() 实际基于 QueryPerformanceCounter,但若硬件不支持或驱动有问题,fallback 到 GetTickCount64,分辨率暴跌。表现为你测出的“10ms”延时,实际波动在 ±15ms 之间,sleep_for(1ms) 根本不起作用。
应对策略:
- 开发期加断言检查:运行时打印
steady_clock::period::num / static_cast<double>(steady_clock::period::den)</double>,确认是否真达到纳秒/微秒级 - 对低延迟要求高的逻辑(如音频、实时控制),别依赖单次
sleep_for,改用 busy-wait +now()轮询(但注意 CPU 占用) - 跨平台项目中,Linux/macOS 下通常没问题,但 Windows CI 必须单独验证 timing 行为
精度不是写出来就有的,得看 OS 和硬件一起点头。chrono 提供的是接口抽象,不是魔法。










