应使用 std::chrono::steady_clock 而非 std::clock() 或 time(),因其保证单调性、跨平台支持且纳秒级精度;std::chrono::high_resolution_clock 虽高精度但不强制稳定,而 steady_clock 语义更明确、更可靠。

为什么不能直接用 std::clock() 或 time()
这两个函数在不同平台下精度极低:std::clock() 返回的是 CPU 时间,Windows 下分辨率常为 10–15ms,Linux 可能稍好但仍是毫秒级;time() 只到秒级。更关键的是,它们不保证单调性(可能回退),也不反映真实墙钟耗时,完全无法支撑纳秒级统计。
std::chrono::high_resolution_clock 是首选,但要注意它的“高精度”不等于“高稳定”
标准规定它是“实现提供的最精确时钟”,但 C++11 到 C++20 中,它在各平台底层映射不同:
• Windows:通常绑定到 QueryPerformanceCounter(),稳定、单调、纳秒级(实际分辨率约 100ns)
• Linux:多数 glibc 实现映射到 clock_gettime(CLOCK_MONOTONIC),同样单调且纳秒级(典型分辨率 1–15ns)
• macOS:基于 mach_absolute_time(),需手动换算,但 std::chrono 封装已处理
实操建议:
- 始终用
std::chrono::nanoseconds作为计时单位输出,避免浮点误差 - 不要假设
high_resolution_clock::is_steady为true—— 虽然主流实现都是,但标准不强制,应运行时检查或直接用steady_clock - 避免跨线程共享单个
time_point对象做减法以外的操作,尤其不要序列化裸值
一个最小可行的跨平台纳秒计时器类
核心是封装起始/结束时间点,并提供纳秒整数差值。不需要虚函数、不依赖第三方库:
class NanoTimer {
std::chrono::steady_clock::time_point start_;
public:
NanoTimer() : start_(std::chrono::steady_clock::now()) {}
<pre class="brush:php;toolbar:false;">uint64_t elapsed_ns() const {
auto end = std::chrono::steady_clock::now();
return std::chrono::duration_cast<:chrono::nanoseconds>(
end - start_).count();
}
void reset() { start_ = std::chrono::steady_clock::now(); }</:chrono::nanoseconds>};
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
说明:
- 用
steady_clock而非high_resolution_clock—— 它明确保证单调、无跳变,且所有平台都支持,语义更清晰 - 返回
uint64_t:纳秒值在 500 年内不会溢出(2^64 ns ≈ 584 年),比double更适合累计、比较、日志打点 - 不提供构造时自动启动以外的模式(如延迟启动),避免状态分支和误用
实际使用中三个容易被忽略的细节
纳秒数字本身很“脆”,稍不注意就失去意义:
- 编译器优化可能把空循环或无副作用代码整个删掉 —— 测试时务必让被测逻辑产生可观察效果(如写 volatile 变量、调用
asm volatile("" ::: "memory")内存栅栏) - 单次测量噪声极大(上下文切换、TLB miss、CPU 频率波动),至少采样 100 次以上取中位数或 p95,别信第一次跑出来的数字
-
elapsed_ns()的调用本身有开销(约 10–50ns),若被测函数本身也只耗几十纳秒,必须做基线扣除,或改用 RAII 自动计时避免手抖
真正难的从来不是拿到纳秒值,而是让这个值能反映你想知道的那个“执行耗时”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










