C++11 引入的 <chrono> 库提供了类型安全的时间处理能力,通过持续时间、时间点和时钟三个核心概念的分离,彻底解决了传统 C 风格时间函数(time_t、clock_t)的类型混乱问题。
一、类结构
<chrono> 库由三个核心组件构成:
| 组件 | 模板类 | 职责 | 典型用途 |
|---|---|---|---|
| 持续时间 | duration<Rep, Period> | 表示一段时间的长度 | seconds(5)、milliseconds(100) |
| 时间点 | time_point<Clock, Duration> | 表示某个时钟上的一个时刻 | system_clock::now() 的返回值 |
| 时钟 | Clock 概念 | 提供时间点的起点(epoch)和 now() 函数 | system_clock、steady_clock、high_resolution_clock |

二、持续时间(duration)
1.定义
template<class Rep, class Period = ratio<1>>
class duration {
Rep rep_; // 滴答计数
public:
// 构造函数
constexpr duration() = default;
template<class Rep2> constexpr explicit duration(const Rep2& r);
template<class Rep2, class Period2>
constexpr duration(const duration<Rep2, Period2>& d);
// 观察器
constexpr Rep count() const; // 返回滴答计数
// 算术运算
constexpr duration operator+() const;
constexpr duration operator-() const;
duration& operator++();
duration operator++(int);
// ... 其他算术运算符
// 类型转换
template<class Rep2, class Period2>
constexpr duration<Rep2, Period2> to() const;
};
其中模板参数Period 是一个 ratio 类型,表示一个滴答代表的秒数。
template<std::intmax_t Num, std::intmax_t Denom = 1>
class ratio {
static constexpr std::intmax_t num = Num; // 分子
static constexpr std::intmax_t den = Denom; // 分母
};
// 预定义的 Period 类型
using atto = ratio<1, 1000000000000000000>; // 10^-18
using femto = ratio<1, 1000000000000000>; // 10^-15
using pico = ratio<1, 1000000000000>; // 10^-12
using nano = ratio<1, 1000000000>; // 10^-9
using micro = ratio<1, 1000000>; // 10^-6
using milli = ratio<1, 1000>; // 10^-3
using centi = ratio<1, 100>; // 10^-2
using deci = ratio<1, 10>; // 10^-1
using deca = ratio<10, 1>; // 10
using hecto = ratio<100, 1>; // 10^2
using kilo = ratio<1000, 1>; // 10^3
using mega = ratio<1000000, 1>; // 10^6
using giga = ratio<1000000000, 1>; // 10^9
using tera = ratio<1000000000000, 1>; // 10^12
using peta = ratio<1000000000000000, 1>; // 10^15
using exa = ratio<1000000000000000000, 1>; // 10^18
2. 预定义持续时间类型
using nanoseconds = duration<long long, nano>;
using microseconds = duration<long long, micro>;
using milliseconds = duration<long long, milli>;
using seconds = duration<long long>;
using minutes = duration<long long, ratio<60>>;
using hours = duration<long long, ratio<3600>>;
using days = duration<long long, ratio<86400>>; // C++20
using weeks = duration<long long, ratio<604800>>; // C++20
using months = duration<long long, ratio<2629746>>; // C++20(近似)
using years = duration<long long, ratio<31556952>>; // C++20(近似)
3. duration 字面量(C++14)
using namespace std::chrono_literals;
auto ns = 100ns; // nanoseconds
auto us = 200us; // microseconds
auto ms = 300ms; // milliseconds
auto s = 4s; // seconds
auto min = 5min; // minutes
auto h = 6h; // hours
auto day = 7d; // days (C++20)
auto week = 8w; // weeks (C++20)
三、时间点(time_point)
1.定义
template<class Clock, class Duration = typename Clock::duration>
class time_point {
Duration d_; // 从时钟纪元开始的持续时间
public:
// 构造函数
time_point(); // 纪元时间点
explicit time_point(const Duration& d);
// 观察器
constexpr Duration time_since_epoch() const;
// 算术运算
time_point& operator+=(const Duration& d);
time_point& operator-=(const Duration& d);
// 类型转换
template<class Duration2>
time_point<Clock, Duration2> to() const;
};
2.特性
| 特性 | 说明 |
|---|---|
| 依赖时钟 | 每个时间点关联一个特定的时钟类型 |
| 依赖持续时间 | 时间点的内部存储使用该时钟的 duration 类型 |
| 算术运算 | 可加/减持续时间,得到新的时间点 |
| 差值运算 | 两个时间点相减得到持续时间 |
| 比较运算 | 时间点之间可比较先后 |
四、时钟(Clock)
时钟是一个概念(不是类模板),满足以下接口的类都可作为时钟:
class Clock {
public:
using duration = /* 某种持续时间类型 */;
using rep = typename duration::rep;
using period = typename duration::period;
using time_point = chrono::time_point<Clock>;
static constexpr bool is_steady; // 是否为稳定时钟(单调递增)
static time_point now() noexcept; // 返回当前时间点
};
1. 三种标准时钟对比
| 时钟 | is_steady | 起点(epoch) | 用途 | 特点 |
|---|---|---|---|---|
system_clock | ❌ false | 1970-01-01 00:00:00 UTC | 挂钟时间,与系统时间同步 | 可转换为 time_t,可能被调整 |
steady_clock | ✅ true | 系统启动后的某个时刻 | 测量时间间隔 | 单调递增,不受系统时间调整影响 |
high_resolution_clock | 取决于实现 | 取决于实现 | 高精度测量 | 通常是 steady_clock 或 system_clock 的别名 |
2.使用示例
(1)基本应用
#include <chrono>
#include <iostream>
int main() {
auto sys_now = std::chrono::system_clock::now();
auto steady_now = std::chrono::steady_clock::now();
auto high_now = std::chrono::high_resolution_clock::now();
std::cout << "system_clock is_steady: " << std::chrono::system_clock::is_steady << std::endl;
std::cout << "steady_clock is_steady: " << std::chrono::steady_clock::is_steady << std::endl;
return 0;
}
(2)测算程序运行时性能
#include <chrono>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std::chrono;
template<typename Func>
auto measure_time(Func&& func) {
auto start = high_resolution_clock::now();
func();
auto end = high_resolution_clock::now();
return duration_cast<microseconds>(end - start);
}
int main() {
// 测量排序耗时
auto duration = measure_time([]() {
std::vector<int> v(100000);
for (int i = 0; i < 100000; ++i) v[i] = rand();
std::sort(v.begin(), v.end());
});
std::cout << "排序耗时: " << duration.count() << " 微秒" << std::endl;
std::cout << "即 " << duration_cast<milliseconds>(duration).count() << " 毫秒" << std::endl;
return 0;
}
五、基础转换
1.时间点与持续时间的转换
(1)使用 duration_cast 进行时间单位转换
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
// 不同精度持续时间之间的转换
seconds s(123);
milliseconds ms = duration_cast<milliseconds>(s);
nanoseconds ns = duration_cast<nanoseconds>(s);
std::cout << "123 seconds = " << ms.count() << " ms" << std::endl;
std::cout << "123 seconds = " << ns.count() << " ns" << std::endl;
// 向下转换(丢失精度)需要显式 cast
seconds s2 = duration_cast<seconds>(milliseconds(1500));
std::cout << "1500 ms = " << s2.count() << " seconds" << std::endl;
// 浮点持续时间
duration<double> fs(1.5);
milliseconds ms2 = duration_cast<milliseconds>(fs);
std::cout << "1.5 seconds = " << ms2.count() << " ms" << std::endl;
return 0;
}
(2)使用 time_point_cast 转换时间点精度
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
auto now = system_clock::now();
// 毫秒精度的时间点
auto ms_tp = time_point_cast<milliseconds>(now);
// 秒精度的时间点
auto s_tp = time_point_cast<seconds>(now);
std::cout << "原始: " << now.time_since_epoch().count() << std::endl;
std::cout << "毫秒: " << ms_tp.time_since_epoch().count() << std::endl;
std::cout << "秒: " << s_tp.time_since_epoch().count() << std::endl;
return 0;
}
2.system_clock 与 time_t 互转
#include <chrono>
#include <ctime>
#include <iostream>
int main() {
auto now = std::chrono::system_clock::now();
// time_point -> time_t
std::time_t tt = std::chrono::system_clock::to_time_t(now);
std::cout << "当前时间: " << std::ctime(&tt);
// time_t -> time_point
std::time_t tt2 = time(nullptr);
auto tp = std::chrono::system_clock::from_time_t(tt2);
return 0;
}
3. 时钟转换
C++20 引入了不同时钟之间的转换能力:
#include <chrono>
#include <iostream>
int main() {
auto sys_now = std::chrono::system_clock::now();
// C++20: 时钟转换
auto utc_now = std::chrono::utc_clock::now();
auto sys_from_utc = std::chrono::clock_cast<std::chrono::system_clock>(utc_now);
// 文件时钟(文件时间戳)
auto file_now = std::chrono::file_clock::now();
return 0;
}
六、日历与时区
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// 日历日期
auto today = year_month_day(floor<days>(system_clock::now()));
std::cout << "今天是: " << today << std::endl;
// 时间点拆分为日期时间组件
auto now = system_clock::now();
auto dp = floor<days>(now);
auto ymd = year_month_day(dp);
auto hms = hh_mm_ss(now - dp);
// 时区
auto zt = zoned_time(current_zone(), now);
std::cout << "本地时间: " << zt << std::endl;
return 0;
}
七、总结
| 组件 | 模板参数 | 核心功能 | 典型操作 |
|---|---|---|---|
duration | Rep, Period | 表示时间长度 | +, -, *, /, count() |
time_point | Clock, Duration | 表示特定时刻 | +, -, time_since_epoch() |
Clock | - | 提供时间起点和 now() | now() |
duration_cast | ToDuration, FromDuration | 时间单位转换 | duration_cast<ms>(s) |
time_point_cast | ToDuration, Clock, FromDuration | 时间点精度转换 | time_point_cast<ms>(tp) |
<chrono> 库通过类型安全和编译时检查,避免了传统时间 API 的单位混淆问题,是现代 C++ 时间处理的基石。

612

被折叠的 条评论
为什么被折叠?



