【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
namespace chrono 
{struct system_clock { // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTimeusing rep                       = long long;using period                    = ratio<1, 10'000'000>; // 100 nanosecondsusing duration                  = _CHRONO duration<rep, period>;using time_point                = _CHRONO time_point<system_clock>;static constexpr bool is_steady = false;// 获取当前时间static time_point now();// time_point 类型转化成 time_tstatic __time64_t to_time_t(const time_point& _Time);// time_t 类型转化成 time_pointstatic time_point from_time_t(__time64_t _Tm);};struct steady_clock { // wraps QueryPerformanceCounterusing rep                       = long long;using period                    = nano;using duration                  = nanoseconds;using time_point                = _CHRONO time_point<steady_clock>;static constexpr bool is_steady = true;static time_point now() noexcept { // get current timeconst long long _Freq = _Query_perf_frequency(); // doesn't change after system bootconst long long _Ctr  = _Query_perf_counter();static_assert(period::num == 1, "This assumes period::num == 1.");// 10 MHz is a very common QPC frequency on modern PCs. Optimizing for// this specific frequency can double the performance of this function by// avoiding the expensive frequency conversion path.constexpr long long _TenMHz = 10'000'000;if (_Freq == _TenMHz) {static_assert(period::den % _TenMHz == 0, "It should never fail.");constexpr long long _Multiplier = period::den / _TenMHz;return time_point(duration(_Ctr * _Multiplier));} else {// Instead of just having "(_Ctr * period::den) / _Freq",// the algorithm below prevents overflow when _Ctr is sufficiently large.// It assumes that _Freq * period::den does not overflow, which is currently true for nano period.// It is not realistic for _Ctr to accumulate to large values from zero with this assumption,// but the initial value of _Ctr could be large.const long long _Whole = (_Ctr / _Freq) * period::den;const long long _Part  = (_Ctr % _Freq) * period::den / _Freq;return time_point(duration(_Whole + _Part));}}};_EXPORT_STD using high_resolution_clock = steady_clock;
} // namespace chrono

1. duration

1.1 分析

template <class _Rep, class _Period> class duration;
  • _Rep 表示一种数值类型,用来表示 _Period 的类型,比如:int, float, double…
  • _Periodratio 类型,表示 用秒表示的时间单位 比如: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);                  // 24hseconds_type s_oneday (60*60*24);          // 86400smilliseconds_type ms_oneday (s_oneday);    // 86400000msseconds_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.1foo*=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 类型的最小值 的 durationstatic duration(min)();
// 返回相应 _Rep 类型的最大值 的 durationstatic 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; truncatereturn 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 不传时间精度,就默认是 secondstd::cout << tp_seconds.time_since_epoch().count() << std::endl;// 用时钟 system_clock::time_point (time_point) 构造对象,时间周期默认是 1/10000000 ssystem_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时间跨度为1daytime_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 timepublic: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};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/191414.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE——简单认识HTML

文章目录 一、简单解释 HTML二、认识 HTML 的结构三、了解HTML中的相关标签1.注释标签2.标题标签3.段落标签 p4. 换行标签 br5.格式化标签6.图片标签解释 src解释 alt解释其他有关 img 标签的属性 7.超链接标签 a8.表格标签9.列表标签10.input 标签11. select 下拉菜单以及 div…

黑马程序员 学成在线项目 第1章 项目介绍环境搭建v3.1

第1章 项目介绍&环境搭建v3.1 1.项目背景 1.1 在线教育市场环境 以下内容摘自艾瑞&#xff1a;2020年在线教育行业洞察&#xff1a;To B赛道篇_网络服务_艾瑞网 在线教育行业是一个有着极强的广度和深度的行业&#xff0c;从校内到校外&#xff1b;从早幼教到职业培训&…

高斯积分-Gaussian Quadrature

https://mathworld.wolfram.com/GaussianQuadrature.html

Os-hackNos-1

Os-hackNos-1 一、主机发现和端口扫描 主机发现 arp-scan -l端口扫描 nmap -P 192.168.80.141二、信息收集 访问80端口&#xff0c;可知目标是ubuntu系统&#xff0c;中间件是Apache 目录扫描&#xff0c;发现两个路径 dirsearch -u http://192.168.80.141/ -e *index.html路…

如何实现用户未登录不可访问系统

在开发web系统时&#xff0c;如果用户不登录&#xff0c;发现用户也可以直接正常访问系统&#xff0c;这种设计本身并不合理&#xff0c;那么我们希望看到的效果是&#xff0c;只有用户登录成功之后才可以正常访问系统&#xff0c;如果没有登录则拒绝访问。那么我们可以使用过滤…

DPDK初始化

rte_eal_init │ ├──rte_cpu_is_supported&#xff1a;检查cpu是否支持 │ ├──rte_atomic32_test_and_set&#xff1a;操作静态局部变量run_once确保函数只执行一次 │ ├──pthread_self() 获取主线程的线程ID,只是用于打印 │ ├──eal_reset_internal_config&#x…

掌握未来技术趋势,Python编程引领人工智能时代

掌握未来技术趋势&#xff0c;Python编程引领人工智能时代 摘要&#xff1a;Python作为一种高级编程语言&#xff0c;在人工智能领域中扮演着越来越重要的角色。本文将通过介绍Python编程的特点、应用场景及发展前景&#xff0c;展望Python未来的发展趋势&#xff0c;并结合代…

数据结构 栈与队列详解!!

一.栈 关于内存中的栈和数据结构中的栈是不同的&#xff0c;本章着重讲的是数据结构的栈。 这是一张关于栈的表达图。从图中可以看出栈很像是一副卡牌&#xff0c;发牌时只能从上取出&#xff0c;即出栈。 而入栈则是像你出牌后&#xff0c;要把你出的牌压在上一张出的牌上面。…

Linux系统编程学习 NO.9——git、gdb

前言 本篇文章简单介绍了Linux操作系统中两个实用的开发工具git版本控制器和gdb调试器。 git 什么是git&#xff1f; git是一款开源的分布式版本控制软件。它不仅具有网络功能&#xff0c;还是服务端与客户端一体的软件。它可以高效的处理程序项目中的版本管理。它是Linux内…

Windows10下Maven3.9.5安装教程

文章目录 1.下载maven2.安装3.配置系统变量3.1.新建系统变量 MAVEN_HOME3.2.编辑系统变量Path 4.CMD命令测试是否安装成功5.配置maven本地仓库6.配置国内镜像仓库 1.下载maven 官网 https://maven.apache.org/download.cgi 点击下载。 2.安装 解压到指定目录 D:\installSoft…

Git企业开发级讲解(四)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、理解分⽀二、创建分支三、切换分⽀四、合并分⽀五、删除分⽀六、合并冲突七、分⽀管理策略…

搭建mysql主从错误集合

1 mysqld --verbose --help --log-bin-index/tmp/tmp.Frnt2oibYI mysqld: Cant read dir of /etc/mysql/conf.d/ my.cnf是在/etc/mysql/conf.d/文件夹下&#xff0c;所以挂载的时候不要写/etc/mysql 2 COLLATION utf8_unicode_ci is not valid for CHARACTER SET latin1 配…