应优先选std::chrono::steady_clock测间隔,因它单调递增、不受系统时间调整影响;需绝对时间戳时才用system_clock。两者精度和移植性有平台差异,转换须用duration_cast。

用 std::chrono::steady_clock 还是 std::chrono::system_clock?
std::chrono::system_clock 返回的是挂钟时间(即系统时间),受 NTP 调整、手动改时影响,不适合测间隔;std::chrono::steady_clock 才是真正单调递增、不受系统时间扰动的时钟,适合纳秒级计时。但注意:steady_clock 的 epoch 是未指定的,不能直接当“时间戳”用(比如存日志、传给其他系统)。
- 如果你要记录“某事件发生时的绝对时间”,必须用
system_clock,哪怕它可能跳变 - 如果你要测函数执行耗时、做超时判断,无条件选
steady_clock - Linux 上
steady_clock通常基于CLOCK_MONOTONIC,system_clock基于CLOCK_REALTIME,这是内核层面的根本区别
system_clock::now() 能否直接拿到纳秒?
能,但得手动转换——system_clock::time_point 默认精度由实现决定(GCC 通常为微秒,Clang 可能是纳秒),不能直接假设。必须显式转成纳秒单位:
auto tp = std::chrono::system_clock::now();
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
tp.time_since_epoch()
).count();
-
tp.time_since_epoch()返回的是从 epoch(1970-01-01 00:00:00 UTC)开始的duration,类型依赖编译器和标准库 -
duration_cast是安全转换的唯一方式,强制截断或补零,不推荐用static_cast或隐式转换 -
.count()返回的是long long类型的纳秒整数,不是浮点,避免精度丢失
Linux 下用 clock_gettime(CLOCK_REALTIME, ...) 更准?
在 glibc 2.17+ 和较新内核上,std::chrono::system_clock::now() 底层就是调 clock_gettime(CLOCK_REALTIME, ...),所以两者纳秒精度一致。但直接调系统 API 有几点实际差异:
-
clock_gettime可以绕过 C++ 标准时钟封装,少一次函数跳转,性能略高(微秒级场景才值得考虑) - 它返回的是
struct timespec,字段tv_sec+tv_nsec,拼起来就是纳秒时间戳,无类型转换开销 - 但移植性差:Windows 没这接口,得切到
GetSystemTimeAsFileTime或QueryPerformanceCounter - 如果你已在用 C++11 以上,没理由弃
system_clock改手写 syscall,除非 profiling 真实测出它是瓶颈
跨平台纳秒时间戳的常见坑
- Windows 上
system_clock 在 MSVC 2015–2019 中默认只有 100ns 精度(对应 FILETIME),不是真纳秒;即使 cast 到 nanoseconds,低位始终是 0
- macOS 上
system_clock 用 mach_absolute_time(),再按 mach_timebase_info 换算,但最终映射到 CLOCK_REALTIME 仍有约 1µs 误差
- 所有平台都需注意:纳秒值极大(2024 年约
1710000000000000000),存成 int64_t 没问题,但别用 unsigned long(32 位平台会溢出)
- 日志或网络传输时,别直接打
time_point 对象——它不可读也不可序列化,务必转成整数纳秒或 ISO8601 字符串
system_clock 在 MSVC 2015–2019 中默认只有 100ns 精度(对应 FILETIME),不是真纳秒;即使 cast 到 nanoseconds,低位始终是 0 system_clock 用 mach_absolute_time(),再按 mach_timebase_info 换算,但最终映射到 CLOCK_REALTIME 仍有约 1µs 误差 1710000000000000000),存成 int64_t 没问题,但别用 unsigned long(32 位平台会溢出) time_point 对象——它不可读也不可序列化,务必转成整数纳秒或 ISO8601 字符串 纳秒级时间戳听着精确,但真正难的是“对齐”:不同线程读的时间是否可比、跨进程通信时要不要加时钟同步、日志里混用 steady_clock 和 system_clock 会不会导致时间倒流……这些细节比怎么取值更常引发线上问题。
立即学习“C++免费学习笔记(深入)”;










