std::chrono::steady_clock是测墙上时间的正确选择,基于硬件计数器、单调不跳变;而system_clock反映日历时间易受系统调整影响,clock()返回CPU时间非墙上时间。

用 std::chrono::steady_clock 获取高精度墙上时间
需要精确测量程序真实耗时(比如 benchmark 或超时控制),必须用单调、不受系统时钟调整影响的时钟。std::chrono::steady_clock 是 C++11 起标准推荐的选择,它基于硬件计数器,不会因 NTP 调整或手动改系统时间而跳变。
常见错误是误用 std::chrono::system_clock:它反映“日历时间”,可能回退或跳跃,测出来的时间差可能为负或严重失真。
实操建议:
- 始终用
steady_clock::now()两次取差,再用duration_cast转成所需单位(如milliseconds) - 避免直接用
time_t或clock()—— 前者精度低,后者在 POSIX 中定义为 CPU 时间,不是墙上时间 - 若需纳秒级精度,确认目标平台支持:
steady_clock的period可能是纳秒、微秒或毫秒,可用decltype(steady_clock::now().time_since_epoch())::period::num查看
std::clock() 为什么不能用来测墙上时间
std::clock() 返回的是进程消耗的 CPU 时间,单位是 CLOCKS_PER_SEC,和实际经过的秒数完全无关。程序休眠、等待 I/O、被调度抢占时,clock() 几乎不增长。
立即学习“C++免费学习笔记(深入)”;
典型错误现象:
- 调用
std::this_thread::sleep_for(2s)后,clock()只增加几毫秒 - 多线程程序中,
clock()累加所有线程的 CPU 时间,结果远大于墙上时间 - 在 WSL 或某些容器环境里,
clock()行为不稳定,甚至返回负值
除非你明确想测 CPU 占用率,否则别碰 clock()。
跨平台兼容性要注意的两个细节
Windows 和 Linux 下 steady_clock 底层实现不同(QueryPerformanceCounter vs clock_gettime(CLOCK_MONOTONIC)),但标准保证语义一致。真正容易出问题的是以下两点:
- Windows 上 VS2015 及更早版本的
steady_clock::now()有约 15ms 的分辨率缺陷,升级编译器或改用QueryPerformanceCounter手动封装可绕过 - 某些嵌入式或旧版 libc(如 uClibc)不完全支持
steady_clock,编译时报error: 'steady_clock' is not a member of 'std::chrono',此时需降级用high_resolution_clock(注意:它在部分平台等价于system_clock,要实测行为)
一个安全、可复用的计时 RAII 封装
手动写两遍 now() 容易漏掉结束点或搞反顺序。用 RAII 自动记录起止时间更可靠:
struct Timer {
using Clock = std::chrono::steady_clock;
Clock::time_point start;
Timer() : start{Clock::now()} {}
template<typename Unit = std::chrono::milliseconds>
typename Unit::rep elapsed() const {
return std::chrono::duration_cast<Unit>(Clock::now() - start).count();
}
};用法简单:
Timer t;// ... 你的代码auto ms = t.elapsed<std::chrono::milliseconds>();
注意:不要把这个对象传进异步任务或跨线程共享——start 是构造时的本地时间点,跨线程无意义;如果要测某段异步逻辑,应在对应线程内构造新 Timer。
最常被忽略的一点:时间测量本身有开销,单次调用 now() 在现代 CPU 上约几十纳秒;若被测函数本身极短(


















