- 1. 核心概念
- 2.
std::chrono::system_clock
- 3.
std::chrono::steady_clock
- 4.
std::chrono::high_resolution_clock
- 5. (非标准但常见)
std::chrono::utc_clock
和std::chrono::tai_clock
(C++20) - 6. 总结与选择指南
std::chrono
库是C++11引入的用于处理时间和日期的高级库。其核心是时钟(Clocks),每个时钟都是一个类型,提供了不同的时间点和时间间隔的度量方式。
C++标准定义了至少三种时钟类型,不同实现(如GCC、Clang、MSVC)可能会提供更多。本文将重点讲解标准要求的三种。
1. 核心概念
在介绍具体时钟前,先理解每个时钟都必须提供的两个核心成员:
- **
now()
**:一个静态成员函数,用于获取当前时间点(time_point
)。例如:auto current_time = std::chrono::system_clock::now();
- **
period
**:一个类型定义(typedef),表示时钟的“滴答周期”(tick period),即时钟计时一次所代表的时间长度(通常是std::ratio
类型)。例如,std::ratio<1, 1000000>
表示每tick是1微秒。 - **
duration
**:一个类型定义,表示时钟使用的时间间隔类型,通常是std::chrono::duration<rep, period>
。rep
是算术类型(如long long
),period
就是上面的滴答周期。 - **
time_point
**:一个类型定义,表示时钟的时间点类型,通常是std::chrono::time_point<Clock, Duration>
。 is_steady
:一个静态布尔常量,指示时钟是否是稳定的(steady)。这是选择时钟的关键属性。- 稳定时钟:意味着时钟的速率是恒定且单调递增的,永远不会调整(例如,不会因为网络时间协议NTP或夏令时而回拨或跳变)。它只适合测量时间间隔。
- 非稳定时钟:意味着时钟可能会被外部因素调整,适合表示“墙上的钟表”时间(wall time),但不适合精确测量流逝的时间。
2. std::chrono::system_clock
2.1. 功能与含义
- 系统时钟,它表示操作系统维护的“实时时钟”(Wall Clock)。
- 它指示的是从某个历史时间点(纪元,epoch)到现在所经过的时间。这个纪元通常是1970年1月1日00:00:00 UTC,也就是Unix时间戳(Unix Time)的纪元。
- 它不是稳定时钟(
is_steady
通常为false
)。系统时间可以被系统管理员、网络时间同步(NTP)或夏令时(DST)修改。这意味着两次调用now()
得到的时间点,后面的可能比前面的值小。
2.2. 主要用途
- 获取当前日历时间(日期和时间):这是它的主要用途。
- 与时间点/时间戳相互转换:因为它通常基于Unix纪元,所以可以很容易地转换为
time_t
,进而与C库函数(如gmtime
,strftime
)或与其他系统交互。 - 记录文件的创建/修改时间、日志时间戳等需要具有人类可读意义的场景。
2.3. 代码示例
1 |
|
3. std::chrono::steady_clock
3.1. 功能与含义
- 稳定时钟,专门为测量时间间隔而设计。
- 它是稳定的(
is_steady
为true
)。它的时间点值保证是单调递增的,不受任何系统时间调整的影响。即使系统时间被往后调了1小时,steady_clock
仍然会按照物理时间稳定地向前走。 - 它的纪元(起始点)是任意的、由具体的实现定义的(通常是程序启动或系统启动时作为时间0点)。你不能将它转换为日历时间。它的唯一用途就是测量时间间隔。
3.2. 主要用途
- 性能基准测试(Benchmarking):测量代码段的执行时间。
- 超时处理:在网络编程或并发编程中计算等待/超时时间。
- 动画/游戏循环:计算帧与帧之间的时间差(delta time)。
- 任何需要精确、可靠的时间间隔测量的场景。
3.3. 代码示例
1 |
|
4. std::chrono::high_resolution_clock
4.1. 功能与含义
- 高分辨率时钟,它旨在提供当前系统所能提供的最小tick周期的时钟,即最高精度的时钟。
- 它是具体实现定义的,通常是
std::chrono::steady_clock
或std::chrono::system_clock
的别名。这意味着:- 它的
is_steady
属性取决于它到底是哪种时钟的别名。 - 它的稳定性没有保证。在有的平台上它是稳定的,在有的平台上它不是。
- 它的
4.2. 主要用途
- 需要最高可能精度的时间点测量的场景。
- 注意:由于其稳定性不确定,除非你非常清楚你的编译平台上的具体实现(并且确认它是稳定的),否则优先使用
std::chrono::steady_clock
来测量时间间隔会更安全、更可移植。high_resolution_clock
的别名特性有时被称为“时钟的幻影”(a clock alias of last resort)。
4.3. 代码示例
1 | // 用法与steady_clock类似,但要注意其稳定性 |
5. (非标准但常见)std::chrono::utc_clock
和std::chrono::tai_clock
(C++20)
从C++20开始,标准库引入了更多用于处理时区和闰秒的时钟,但这些还不是所有编译器都完全支持的。
- **
utc_clock
**:表示协调世界时(UTC),它会考虑闰秒。 - **
tai_clock
**:表示国际原子时(TAI),它不考虑闰秒,是一个纯粹基于原子钟的连续时间尺度。
6. 总结与选择指南
特性 | system_clock |
steady_clock |
high_resolution_clock |
---|---|---|---|
用途 | 获取日历时间 | 测量时间间隔 | 测量高精度时间间隔 |
稳定性 | 否(可调整) | 是(单调递增) | 具体实现定义(可能稳定也可能不稳定) |
纪元 | 通常为Unix纪元 (1970) | 任意(程序/系统启动) | 具体实现定义 |
可转换日历 | 是(通过to_time_t ) |
否 | 否 |
推荐场景 | 记录时间戳、与外部系统交互 | 性能测试、超时、游戏循环 | 需要最高精度,且不关心可移植性 |
6.1. 黄金法则
- 想要“现在几点?”(日历/日期/时间) -> 用
system_clock
- 想要“这段代码跑了多久?”(时间间隔) -> **优先使用
steady_clock
**(最安全可靠) - 除非有极端精度需求且了解当前平台具体实现,否则慎用
high_resolution_clock
。