最可靠方式是用 static const auto program_start = std::chrono::steady_clock::now(); 在 main 开头或全局作用域初始化,后续用 duration_cast 转换单位后计算差值,避免 system_clock 和非静态局部初始化导致的时钟跳变或竞态。

用 std::chrono 获取程序已运行时间,最可靠的方式是记录启动时刻,之后用当前时刻减去它——不是读系统时间,也不是靠 clock(),因为后者受 CPU 调度、多线程抢占影响大,精度和语义都不够稳。
如何在程序启动时记录起始时间点
把 std::chrono::steady_clock::now() 存进一个全局或静态变量里,确保它在 main() 开头就执行。别用 system_clock,它可能被系统管理员调时,导致差值跳变;steady_clock 才是专为测量间隔设计的。
常见错误:在函数内首次调用时才初始化,结果多线程下可能重复赋值或竞态;或者用 auto start = std::chrono::system_clock::now();,后续遇到 NTP 同步就会出负值或突变。
- 推荐写法:
static const auto program_start = std::chrono::steady_clock::now();
- 如果必须放函数里(比如封装成工具类),加
static修饰并确保只初始化一次 - 不要在 DLL/so 的全局对象构造器中做这事——加载顺序不可控,
steady_clock::now()可能尚未就绪
怎么算出“已运行多少秒/毫秒/微秒”
用当前时间减去 program_start,再通过 duration_cast 转成你需要的单位。注意:直接用 .count() 拿到的是底层时钟滴答数(可能是纳秒级整数),不转换单位就打印会严重误导。
立即学习“C++免费学习笔记(深入)”;
典型误用:auto d = std::chrono::steady_clock::now() - program_start; std::cout —— 这输出的是纳秒数,不是秒。
- 要秒:
std::chrono::duration_cast<std::chrono::seconds>(d).count()
- 要毫秒(常用):
std::chrono::duration_cast<std::chrono::milliseconds>(d).count()
- 要带小数的秒(如用于日志):
std::chrono::duration<double>(d).count()
- 避免反复 cast:如果高频调用(如每帧测时),先 cast 成
double或int64_t缓存,别每次重算
为什么不用 clock() 或 gettimeofday()
clock() 返回的是进程 CPU 时间,不是真实流逝时间;多线程下它累加所有线程的占用,且在 Windows 上分辨率常只有 10–15ms;Linux 上虽可到微秒,但语义仍是 CPU 时间,程序 sleep 时它几乎不动。而 gettimeofday() 是系统时间,会被 NTP 校正、手动改时打乱,不能用于测间隔。
实测对比:程序 sleep(5),clock() 可能只增加几毫秒;gettimeofday() 若中途被校准 -1 秒,差值就变负;steady_clock 则稳定增长约 5000ms。
-
clock()适合分析某段代码占用了多少 CPU 资源 -
steady_clock才适合回答“程序已经跑了多久”这个物理时间问题 - Windows 下
QueryPerformanceCounter和 Linux 下clock_gettime(CLOCK_MONOTONIC)是steady_clock的底层实现,你不用操心跨平台细节
真正要注意的不是“怎么写”,而是“在哪记起点”和“怎么转单位”。起点记晚了(比如进了某个函数才记),后面所有时间都偏小;单位转错了(比如该用 milliseconds 却用了 seconds),数值差三个数量级。这两个点错一个,结果就完全不可信。


















