【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.mzph.cn/news/148057.shtml

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

相关文章

python使用selenium webDriver时 报错

可能原因和解决&#xff1a; 1. python 解释器 ----> 设置 2. 浏览器版本 与 浏览器驱动版本不一致 ----> 安装同一版本的 (下载chromedriver | 谷歌驱动更高版本的测试版) 参考&#xff1a;Python使用Selenium WebDriver的入门介绍及安装教程-CSDN博客 Selenium安…

设计模式-行为型模式-策略模式

一、什么是策略模式 策略模式是一种行为设计模式&#xff0c;它允许在运行时选择算法或行为&#xff0c;并将其封装成独立的对象&#xff0c;使得这些算法或行为可以相互替换&#xff0c;而不影响使用它们的客户端。&#xff08;ChatGPT生成&#xff09; 主要组成部分&#xff…

基于django的在线教育系统

基于python的在线教育系统 摘要 基于Django的在线教育系统是一种利用Django框架开发的现代化教育平台。该系统旨在提供高效、灵活、易用的在线学习体验&#xff0c;满足学生、教师和管理员的需求。系统包括学生管理、课程管理、教师管理、视频课程、在线测验等核心功能。系统采…

在线 sha1 加密

ttmd5 http://www.ttmd5.com/hash.php?type5 qqxiuzi https://www.qqxiuzi.cn/bianma/sha-1.htm jb51 http://tools.jb51.net/password/sha_encode

23111707[含文档+PPT+源码等]计算机毕业设计基于javawebmysql的旅游网址前后台-全新项目

文章目录 **软件开发环境及开发工具&#xff1a;****功能介绍&#xff1a;****论文截图&#xff1a;****实现&#xff1a;****代码:** 编程技术交流、源码分享、模板分享、网课教程 &#x1f427;裙&#xff1a;776871563 软件开发环境及开发工具&#xff1a; 前端使用技术&a…

mock测试数据

1.下载一个jar 架包 地址&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1G5rVF5LlIYpyU-_KHsGjOA?pwdab12 提取码&#xff1a;ab12 2.配置当前电脑java环境变量 3.在同一文件目录下创建json 数据4.在终端切换到当前目录下启动服务&#xff0c; java -jar ./moco-r…

使用百度翻译API或腾讯翻译API做一个小翻译工具

前言 书到用时方恨少&#xff0c;只能临时抱佛脚。英文pdf看不懂&#xff0c;压根看不懂。正好有百度翻译API和腾讯翻译API&#xff0c;就利用两个API自己写一个简单的翻译工具&#xff0c;充分利用资源&#xff0c;用的也放心。 前期准备 关键肯定是两大厂的翻译API&#x…

IDEA 集成 Docker 插件一键部署 SpringBoot 应用

目录 前言IDEA 安装 Docker 插件配置 Docker 远程服务器编写 DockerFileSpringBoot 部署配置SpringBoot 项目部署结语 前言 随着容器化技术的崛起&#xff0c;Docker成为了现代软件开发的关键工具。在Java开发中&#xff0c;Spring Boot是一款备受青睐的框架&#xff0c;然而&…

kubenetes-服务发现和负载均衡

一、服务发布 kubenetes把服务发布至集群内部或者外部&#xff0c;服务的三种不同类型&#xff1a; ClusterlPNodePortLoadBalancer ClusterIP是发布至集群内部的一个虚拟IP,通过负载均衡技术转发到不同的pod中。 NodePort解决的是集群外部访问的问题&#xff0c;用户可能不…

debian 修改镜像源为阿里云【详细步骤】

文章目录 修改步骤第 1 步:安装 vim 软件第 2 步:备份源第 3 步:修改为阿里云镜像参考👉 背景:在 Docker 中安装了 jenkins 容器。查看系统,发现是 debian 11(bullseye)。 👉 目标:修改 debian bullseye 的镜像为阿里云镜像,加速软件安装。 修改步骤 第 1 步:…

限制Domain Admin登录非域控服务器和用户计算机

限制Domain Admin管理员使用敏感管理员帐户(域或林中管理员组、域管理员组和企业管理员组中的成员帐户)登录到信任度较低的服务器和用户端计算机。 此限制可防止管理员通过登录到信任度较低的计算机来无意中增加凭据被盗的风险。 建议采用的策略 建议使用以下策略限制对信任度…

SPASS-偏相关分析

基本概念 偏相关分析的任务就是在研究两个变量之间的线性相关关系时控制可能对其产生影响的变量,这种相关系数称为偏相关系数。偏相关系数的数值和简单相关系数的数值常常是不同的,在计算简单相关系数时,所有其他自变量不予考虑。 统计原理 控制一个变量和控制两个变量的偏…

Python winreg将cmd/PowerShell(管理员)添加到右键菜单

效果 1. 脚本 用管理员权限运行&#xff0c;重复执行会起到覆盖效果&#xff08;根据sub_key&#xff09;。 icon自己设置。text可以自定义。sub_key可以改但不推荐&#xff08;避免改成和系统已有项冲突的&#xff09;。command不要改。 from winreg import *registry r&q…

ubuntu20.04安装cv2

查看ubuntu的版本 cat /etc/lsb-release DISTRIB_IDUbuntu DISTRIB_RELEASE20.04 DISTRIB_CODENAMEfocal DISTRIB_DESCRIPTION"Ubuntu 20.04.3 LTS"更改镜像源 cp /etc/apt/sources.list /etc/apt/sources.list.bak cat > /etc/apt/sources.listdeb http://mirr…

使用Docker部署Python Flask应用的完整教程

一、引言 Docker是一种开源的容器化平台&#xff0c;可以将应用程序及其依赖项打包成一个独立的容器&#xff0c;实现快速部署和跨平台运行。本文将详细介绍如何使用Docker来部署Python Flask应用程序&#xff0c;帮助开发者更高效地构建和部署应用。 二、准备工作 在开始之前…

4-flask-cbv源码、Jinja2模板、请求响应、flask中的session、flask项目参考

1 flask中cbv源码 2 Jinja2模板 3 请求响应 4 flask中的session 5 flask项目参考 1 flask中cbv源码 ***flask的官网文档&#xff1a;***https://flask.palletsprojects.com/en/3.0.x/views/1 cbv源码执行流程1 请求来了&#xff0c;路由匹配成功---》执行ItemAPI.as_view(item…

软件质量保护与测试(第2版)学习总结第十三章 集成测试

很多人都认为微软是一家软件开发公司&#xff0c;事实上我们是一家软件测试公司。 ---比尔盖茨 集成测试是在单元测试的基础上将多个模块组合在一起进行测试的过程。 13.1.1 区别 单元测试主要关注模块内部&#xff0c;系统测试则是在用户的角度来评价系统&#xff…

Pikachu漏洞练习平台之XXE(XML外部实体注入)

目录 什么是 XML&#xff1f; 什么是DTD&#xff1f; 什么是XEE&#xff1f; 常见payload 什么是 XML&#xff1f; XML 指可扩展标记语言&#xff08;EXtensible Markup Language&#xff09;&#xff1b; XML 不会做任何事情&#xff0c;而是用来结构化、存储以及传输信息…

10、背景分离 —— 大津算法

上一节学习了通过一些传统计算机视觉算法,比如Canny算法来完成一个图片的边缘检测,从而可以区分出图像的边缘。 今天再看一个视觉中更常见的应用,那就是把图片的前景和背景的分离。 前景和背景 先看看什么是前景什么是背景。 在图像处理和计算机视觉中,"前景"…

CTFhub-RCE-过滤空格

1. 查看当前目录&#xff1a;127.0.0.1|ls 2. 查看 flag_890277429145.php 127.0.0.1|cat flag_890277429145.php 根据题目可以知道空格被过滤掉了 3.空格可以用以下字符代替&#xff1a; < 、>、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等 $IFS在li…