【C++】chono库:使用及源码分析

本文详细介绍了C++chrono库中的duration和time_point类,包括它们的定义、类型转换方法(如duration_cast和time_point_cast)、实例应用以及time_point的time_since_epoch功能。同时,讨论了三种不同的clock类型:system_clock、steady_clock和high_resolution_clock。
文章目录
  • 0. 概述
  • 1. duration
    • 1.1 分析
      • std::chrono::duration_cast()
    • 1.2 使用案例
      • std::chrono::duration::count()
    • 1.3 部分源码
  • 2. time_point
    • 2.1 分析
      • std::chrono::time_point_cast()
    • 2.2 使用举例
      • std::chrono::time_point::time_since_epoch()
    • 2.3 部分源码

0. 概述

本篇文章介绍 chrono 模板库,是参考 cplusplus.com 官网做的一篇详解。
chrono 库是可以实现各种时间格式的定义和转化,整体分成三部分。

  1. duration 类
    用作 测量时间跨度,比如:1分钟,2小时,或者10毫秒。
    使用 duration 类模板的对象来表示时,可以将计数表示和周期精度耦合在一起(例如:10表示计数,毫秒表示周期精度)
  2. time_point 类
    用作 表示某一个时间点,比如:日出的时间,某人的纪念日
    使用 time_point 类模板的对象来表示时,需要指定 clock(三种,后面有讲) 和相对于纪元的持续时间来表示这一点
namespace chrono 
{
	// duration 类
	template <class _Rep, class _Period> class duration;
	// time_point 类
	template <class _Clock, class _Duration = typename _Clock::duration> class time_point;
	// ...
}
  1. clock 结构体
    就像名称所示,时钟,可以将时间点与实际物理时间联系起来。
    主要介绍三个时钟,它们提供了将当前时间表示为时间点的方法
    1. 系统时钟 system_clock
    2. 稳定时钟 steady_clock
    3. 高精度时钟 high_resolution_clock

1. duration

1.1 分析

template <class _Rep, class _Period> class duration;
  • _Rep 表示一种数值类型,用来表示 _Period 的类型,比如:int, float, double…
  • _Period 是 ratio 类型,表示 用秒表示的时间单位 比如:second, milisecond…

常用的duration<Rep,Period>已经定义好了,在 std::chrono下:

// std::chrono
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<int, ratio<60>>;
using hours			= duration<int, ratio<3600>>;
using days			= duration<int, ratio_multiply<ratio<24>, hours::period>>;
using weeks			= duration<int, ratio_multiply<ratio<7>, days::period>>;
using years			= duration<int, ratio_multiply<ratio<146097, 400>, days::period>>;
using months		= duration<int, ratio_divide<years::period, ratio<12>>>;
std::chrono::duration_cast()

由于 duration 的种类繁多,chrono 库提供了duration_cast 类型转换函数模板,在模板参数中填写需要转成的类型如:<std::chrono::seconds / months / days…>,就可以得到想要的结果,std::chrono 下:

// std::chrono
template <class _To, class _Rep, class _Period, enable_if_t<_Is_duration_v<_To>, int> /* = 0 */>
    _To duration_cast(const duration<_Rep, _Period>& _Dur)

1.2 使用案例

🌰典型的用法是表示一段时间:

// duration constructor
#include <iostream>
#include <chrono>
	
int main ()
{
	typedef std::chrono::duration<int> seconds_type;
	typedef std::chrono::duration<int,std::milli> milliseconds_type;
	typedef std::chrono::duration<int,std::ratio<60*60>> hours_type;
	
	hours_type h_oneday (24);                  // 24h
	seconds_type s_oneday (60*60*24);          // 86400s
	milliseconds_type ms_oneday (s_oneday);    // 86400000ms
	
	seconds_type s_onehour (60*60);            // 3600s
	//hours_type h_onehour (s_onehour);          // NOT VALID (type truncates), use:
	hours_type h_onehour (std::chrono::duration_cast<hours_type>(s_onehour));
	milliseconds_type ms_onehour (s_onehour);  // 3600000ms (ok, no type truncation)
	
	std::cout << ms_onehour.count() << "ms in 1h" << std::endl;
	
	return 0;
}
--------------------------
输出结果:
3600000ms in 1h
  • 需要注意的就是,大单位的 duration 可以作为参数构造小单位,反过来就不行了,需要使用 duration_cast 进行强转。
    在这里插入图片描述
std::chrono::duration::count()

🌰 duration 还有一个成员函数 count() 返回 Rep 类型的 Period 数量:

// duration::count
#include <iostream>     
#include <chrono>       // std::chrono::seconds, std::chrono::milliseconds,std::chrono::duration_cast
using namespace std::chrono;

int main ()
{
	milliseconds foo (1000); // 1 second,这里的 milliseconds 是库里的,定义见 1.1
	foo*=60;
	
	std::cout << "duration (in periods): ";
	std::cout << foo.count() << " milliseconds.\n";
	
	std::cout << "duration (in seconds): ";
	std::cout << foo.count() * milliseconds::period::num / milliseconds::period::den;
	std::cout << " seconds.\n";
	
	return 0;
}
-------------------------------
输出结果:
duration (in periods): 60000 milliseconds.
duration (in seconds): 60 seconds.

1.3 部分源码

template <class _Rep, class _Period>
class duration { // represents a time duration
public:
    using rep    = _Rep;
    using period = typename _Period::type;

    template <class _Rep2, enable_if_t<is_convertible_v<const _Rep2&, _Rep> && (treat_as_floating_point_v<_Rep> !treat_as_floating_point_v<_Rep2>), int> = 0>
    duration(const _Rep2& _Val) : _MyRep(static_cast<_Rep>(_Val)) {}
    
    template <class _Rep2, class _Period2, enable_if_t<treat_as_floating_point_v<_Rep> || (_Ratio_divide_sfinae<_Period2, _Period>::den == 1 && !treat_as_floating_point_v<_Rep2>), int> = 0>
    duration(const duration<_Rep2, _Period2>& _Dur) : _MyRep(_CHRONO duration_cast<duration>(_Dur).count()) {}

    _Rep count() const 
    {
        return _MyRep;
    }

    common_type_t<duration> operator+() const;
    common_type_t<duration> operator-() const;
    duration& operator++();
    duration operator++(int);
    // -- (略)
    duration& operator+=(const duration& _Right);
    duration& operator-=(const duration& _Right);
    // *= /= %= (略)

// 返回为 0 的 duration 类型
    static duration zero();
// 返回相应 _Rep 类型的最小值 的 duration
    static duration(min)();
// 返回相应 _Rep 类型的最大值 的 duration
    static duration(max)();

private:
    _Rep _MyRep; // the stored rep
};

2. time_point

2.1 分析

template <class _Clock, class _Duration = typename _Clock::duration> class time_point;

类型 std::chrono::time_point 表示一个具体时间,鉴于我们使用时间的情景不同,这个 time point 具体到什么程度,由选用的单位决定。模板参数如下:

  • 时钟类型(见 clock 部分)
  • duration 的时间类型,决定了 time_point 的时间类型
std::chrono::time_point_cast()

由于各种 time_point 表示方式不同,chrono 也提供了相应的转换函数 time_point_cast()。

template <class _To, class _Clock, class _Duration, enable_if_t<_Is_duration_v<_To>, int> = 0>
time_point<_Clock, _To> time_point_cast(const time_point<_Clock, _Duration>& _Time);
{
	// change the duration type of a time_point; truncate
	return time_point<_Clock, _To>(_CHRONO duration_cast<_To>(_Time.time_since_epoch()));
}

2.2 使用举例

以 system_clock 这个时钟举例,里面涉及的起始时间,是计算机元年 1970年1月1日8点(后文简称计元)。

🌰代码如下:

// time_point constructors
#include <iostream>
#include <chrono>
using namespace std::chrono;

int main ()
{
	// 用时钟 system_clock::time_point 直接声明,其值默认为:纪元时间
	system_clock::time_point tp_epoch;
	std::time_t tt = system_clock::to_time_t(tp_epoch);		// 转成 time_t 后可查

	// 用 time_point 类(tp_seconds 的时间周期是 second)
	time_point<system_clock, duration<int>> tp_seconds(duration<int>(1));	// duration 不传时间精度,就默认是 second
	std::cout << tp_seconds.time_since_epoch().count() << std::endl;

	// 用时钟 system_clock::time_point (time_point) 构造对象,时间周期默认是 1/10000000 s
	system_clock::time_point tp(tp_seconds);
	std::cout << "1 second since system_clock epoch = ";
	std::cout << tp.time_since_epoch().count();
	std::cout << " system_clock periods." << std::endl;

	// 打印
	std::cout << "time_point tp_epoch is: " << ctime(&tt);
	tt = system_clock::to_time_t(tp);
	std::cout << "time_point tp is:       " << ctime(&tt);

	return 0;
}
------------------------------
输出结果:
1
1 second since system_clock epoch = 10000000 system_clock periods.
time_point tp_epoch is : Thu Jan  1 08 : 00 : 00 1970
time_point tp is : Thu Jan  1 08 : 00 : 01 1970
std::chrono::time_point::time_since_epoch()

time_point 有一个函数 time_since_epoch() 用来获得1970年1月1日到 time_point 时间经过的duration。同样,如果 time_point 以天为单位,函数返回的 duration 就以天为单位。

#include <iostream>
#include <chrono>
using namespace std::chrono;

int main()
{
	typedef duration<int, std::ratio<60 * 60 * 24>> days_type;	// ratio以second为单位,这里的duration时间跨度为1day
	time_point<system_clock, days_type> today = time_point_cast<days_type>(system_clock::now());
	std::cout << today.time_since_epoch().count() << " days since epoch" << std::endl;

	return 0;
}
--------------------
输出结果:
19679 days since epoch

2.3 部分源码

template <class _Clock, class _Duration = typename _Clock::duration>
    class time_point { // represents a point in time
    public:
        using clock    = _Clock;
        using duration = _Duration;
        using rep      = typename _Duration::rep;
        using period   = typename _Duration::period;

        time_point(const _Duration& _Other): _MyDur(_Other) {}

        template <class _Duration2, enable_if_t<is_convertible_v<_Duration2, _Duration>, int> = 0>
        constexpr time_point(const time_point<_Clock, _Duration2>& _Tp): _MyDur(_Tp.time_since_epoch()) {}

        _Duration time_since_epoch() const
        {
            return _MyDur;
        }

        time_point& operator++() noexcept(is_arithmetic_v<rep>);
        time_point operator++(int) noexcept(is_arithmetic_v<rep>);
        time_point& operator--() noexcept(is_arithmetic_v<rep>);
        time_point operator--(int) noexcept(is_arithmetic_v<rep>);
        time_point& operator+=(const _Duration& _Dur);
        time_point& operator-=(const _Duration& _Dur);
        static time_point(min)();
        static time_point(max)();

    private:
        _Duration _MyDur{duration::zero()}; // duration since the epoch
    };

【C++】chono库:使用及源码分析_chrono源码-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值