应使用 std::chrono::steady_clock 测量进程真实运行时间,它跨平台封装了 clock_monotonic 和 queryperformancecounter,保证单调稳定;避免使用 system_clock(受系统时间跳变影响)或 high_resolution_clock(可能退化)。

Linux/macOS 下用 clock_gettime 获取进程真实运行时间
要获取当前程序从启动到现在的实际耗时(墙上时钟时间),clock_gettime(CLOCK_MONOTONIC, ...) 是最可靠的选择。它不受系统时间调整影响,精度通常达纳秒级,且在大多数现代 Linux 和 macOS 上都可用。
常见错误是误用 CLOCK_REALTIME:它会随 date 或 NTP 调整跳变,导致计时结果不可靠;还有人用 time(),但只能到秒级,且同样受系统时间修改干扰。
-
CLOCK_MONOTONIC从系统启动开始单调递增,适合测量持续时间 - 需要包含头文件:
#include <time.h></time.h> - 注意 struct
timespec的tv_sec(秒)和tv_nsec(纳秒),相加后转为 double 秒更方便计算 - 首次调用应在 main 开头记录起点,后续任意位置调用取差值
struct timespec start; clock_gettime(CLOCK_MONOTONIC, &start); <p>// ... 中间执行逻辑 ...</p><p>struct timespec end; clock_gettime(CLOCK_MONOTONIC, &end); double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; </p>
Windows 下用 QueryPerformanceCounter 替代
Windows 没有 clock_gettime,等效方案是 QueryPerformanceCounter 配合 QueryPerformanceFrequency。它提供高精度、单调的硬件计数器,行为与 CLOCK_MONOTONIC 最接近。
容易踩的坑是直接用 GetTickCount64:它只有毫秒精度,且 49.7 天后会回绕(虽 64 位版不溢出,但精度仍不足);clock() 返回的是 CPU 时间,不是墙上时间,多线程下意义混乱。
- 必须先调用
QueryPerformanceFrequency获取频率,否则无法换算成秒 - 返回值是
LARGE_INTEGER,建议用.QuadPart成员读取 - 跨平台封装时,可定义宏或 inline 函数统一接口,避免散落平台判断
LARGE_INTEGER freq, start, end; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&start); // ... 执行 ... QueryPerformanceCounter(&end); double elapsed = (double)(end.QuadPart - start.QuadPart) / freq.QuadPart;
用 std::chrono::steady_clock 实现跨平台简化
C++11 起,std::chrono::steady_clock 就是 CLOCK_MONOTONIC 和 QueryPerformanceCounter 的标准封装。只要编译器支持(GCC 4.8+、Clang 3.2+、MSVC 2015+),它就能自动选对底层时钟,无需条件编译。
有人误以为 system_clock 更“准确”,但它对应 CLOCK_REALTIME,依然受系统时间跳变影响;也有人用 high_resolution_clock,但它只是别名,在某些旧实现里可能退化为 system_clock,不可靠。
-
steady_clock保证单调、稳定、无跳变,是测量间隔的唯一推荐选择 - 直接用
duration_cast<seconds></seconds>或duration_cast<milliseconds></milliseconds>提取整型值,或用count()+ 单位换算保留浮点精度 - 注意:不能用
steady_clock::to_time_t()—— 它未定义,也不该有含义
auto start = std::chrono::steady_clock::now(); // ... 执行 ... auto end = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast<:chrono::microseconds>(end - start).count(); </:chrono::microseconds>
终端运行时间 ≠ 进程生命周期时间
如果用户真正想问的是“这个终端窗口开了多久”,那根本没法用 C++ 程序直接获取 —— 终端模拟器(如 gnome-terminal、iTerm2、Windows Terminal)不向子进程暴露自己的启动时间,也没有统一 IPC 接口。所谓“当前终端运行时间”是个模糊概念,实际场景中几乎总是指当前程序自身的运行时长。
试图通过 /proc/self/stat(Linux)读取进程启动时间戳,或 GetProcessTimes(Windows)拿到创建时间再算差值,确实可行,但要注意:start_time 字段单位是 jiffies(Linux),需结合 sysconf(_SC_CLK_TCK) 换算;而 Windows 的 FILETIME 是 100 纳秒单位,需转为 epoch 时间再减。这些方法比 steady_clock 更重、更慢,且无额外收益。
真正需要区分“终端存活”和“程序存活”的场景极少,绝大多数时候,你只需要一个稳定、单调、易用的计时器 —— steady_clock 就是答案。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











