C++ chrono库结构

C++11 引入的 <chrono> 库提供了类型安全的时间处理能力,通过持续时间时间点时钟三个核心概念的分离,彻底解决了传统 C 风格时间函数(time_tclock_t)的类型混乱问题。

一、类结构

<chrono> 库由三个核心组件构成:

组件模板类职责典型用途
持续时间duration<Rep, Period>表示一段时间的长度seconds(5)milliseconds(100)
时间点time_point<Clock, Duration>表示某个时钟上的一个时刻system_clock::now() 的返回值
时钟Clock 概念提供时间点的起点(epoch)和 now() 函数system_clocksteady_clockhigh_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❌ false1970-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;
}

七、总结

组件模板参数核心功能典型操作
durationRepPeriod表示时间长度+-*/count()
time_pointClockDuration表示特定时刻+-time_since_epoch()
Clock-提供时间起点和 now()now()
duration_castToDurationFromDuration时间单位转换duration_cast<ms>(s)
time_point_castToDurationClockFromDuration时间点精度转换time_point_cast<ms>(tp)

<chrono> 库通过类型安全编译时检查,避免了传统时间 API 的单位混淆问题,是现代 C++ 时间处理的基石。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万法若空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值