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

文章目录
  • 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博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: std::chrono::duration_cast是C++11标准中的一个函数模板,用于将一个时间段(duration)从一个时间单位转换为另一个时间单位。它的语法如下: template <class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d); 其中,ToDuration是目标时间单位的类型,Rep是时间段的计数类型,Period是时间段的计数单位。该函数返回一个ToDuration类型的时间段,表示将输入的时间段d转换为目标时间单位的时间段。 例如,将一个以秒为单位的时间段转换为以毫秒为单位的时间段,可以使用以下代码: std::chrono::duration<double> seconds(1.5); std::chrono::milliseconds milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(seconds); 这里,我们定义了一个以秒为单位的时间段seconds,然后使用duration_cast将其转换为以毫秒为单位的时间段milliseconds。最终,milliseconds的值为1500毫秒。 ### 回答2: std::chrono::duration_cast是C++11标准中的一个模板函数,用于将std::chrono::duration类型的时间间隔值转换为其他时间间隔单位的类型。在C++中,时间间隔可以被表示为不同的时间单位,例如纳秒、微秒、毫秒、秒、分、时、天等等。std::chrono::duration_cast函数可以在这些时间单位之间进行转换。 std::chronoC++标准中关于时间的新特性,它提供了一组新的类和函数,方便我们处理时间相关的问题。std::chrono::duration是C++标准中表示时间间隔的类,它的实现方式是以纳秒为基础单位,使用模板来实现长度可变的时间间隔类型。 std::chrono::duration_cast函数的原型如下: ``` template <class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d); ``` 其中,ToDuration代表要转换成的时间间隔类型,Rep代表时间间隔的值的类型,Period代表时间间隔的单位。std::chrono::duration_cast函数接收一个std::chrono::duration类型的参数,并将其转换为ToDuration类型的值。ToDuration必须是std::chrono::duration类型的模板实例,且单位必须是能由被转换的std::chrono::duration类型表示的单位。转换过程中,精度可能会有损失。 使用std::chrono::duration_cast函数进行时间间隔转换的示例代码如下: ``` #include <chrono> #include <iostream> int main() { std::chrono::milliseconds ms(100); std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(ms); std::cout << s.count() << " seconds" << std::endl; return 0; } ``` 在上面的代码中,我们定义了一个std::chrono::milliseconds类型的变量ms,它表示了100毫秒的时间间隔。然后,我们使用std::chrono::duration_cast函数,将ms转换成了std::chrono::seconds类型的变量s,并输出了它的值。从输出可以看出,这个时间间隔确实被正确地转换成了秒。 总之,std::chrono::duration_cast函数是C++11标准中用于时间间隔转换的重要工具函数,它可以将一个时间间隔值在不同的时间单位之间进行转换。使用这个函数可以方便地进行时间的计算和比较。 ### 回答3: std::chrono::duration_cast是C++11中的一个类型转换函数模板,用于将一个时间间隔(duration)从一个时间单位转换为另一个时间单位。可用于将高分辨率时钟的时间戳转换为较小时间精度的值,或将时间精度从毫秒转换为微秒。 std::chrono::duration_cast函数需要两个参数:目标类型和源类型,其中源类型是一个时间间隔(duration)类型,表示一段时间长度,而目标类型是任何代表时间单位的类型,如std::chrono::seconds,std::chrono::milliseconds或std::chrono::microseconds等。 函数的作用是将源类型的时间间隔转换为目标类型的时间间隔。这个转换是通过对源类型和目标类型之间的比例关系进行简单的算术运算来实现的。 简单使用示例: ```c++ #include <iostream> #include <chrono> int main() { std::chrono::milliseconds ms(1000); std::chrono::microseconds us = std::chrono::duration_cast<std::chrono::microseconds>(ms); std::cout << us.count() << "us\n"; // 输出结果:1000000us return 0; } ``` 在上述示例中,我们定义了一个名为ms的std::chrono::milliseconds类型的变量,表示1000毫秒的时间间隔。然后我们使用std::chrono::duration_cast函数将这个时间间隔转换为std::chrono::microseconds类型的时间间隔,并将结果存储在一个名为us的变量中。最后,我们将us的计数值打印到控制台上,以确保转换正确。 总之,std::chrono::duration_cast是一个非常实用的函数模板,可用于将时间间隔从一种时间单位转换为另一种时间单位,从而实现时间间隔的转换和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值