> 文章列表 > C++:Reference:chrono学习

C++:Reference:chrono学习

C++:Reference:chrono学习

chrono

  • 概述
  • 1:Durations
    • 1.1 :Duration构造函数
    • 1.2 静态成员函数count
    • 1.3 duration_cast分析
  • 2:Time points
  • 3:clocks
  • 几个问题需要说明
  • 实际应用

概述

Time library

  • chrono 是 header 名称,也是子命名空间的名称:此header头中的所有元素不是直接在std命名空间下定义的(这与大多数标准库一样),而是在 std::chrono命名空间下定义。
  • 在 chrono header 文件中的元素是处理时间的,主要通过下面三个概念实现。
    C++:Reference:chrono学习

1:Durations

  • 它测量的是时间跨度,比如:一分钟,两小时或十毫秒。
  • 在这个库中,用持续时间类模板对象来表示:该模板将计数表示和周期精度相耦合(例如:10毫秒,10作为计数表示,毫秒作为周期精度)。

1.1 :Duration构造函数

#include<iostream>
#include<ratio>
#include<chrono>
int main()
{// 定义一个秒为单位来衡量时间间隔的情况。typedef std::chrono::duration<int> seconds_type;// 这里定义了一个duration类型,这个类型需要两个参数:第一个参数是时间长度的类型(int类型),第二个参数是时间单位(这里是毫秒)typedef std::chrono::duration<int,std::milli> milliseconds_type;// 这里定义了一个duration类型,这个类型需要两个参数,第一个参数指定了时间长度的基本单位(在这里是int 表示是整数),第二个参数指定时间之间的比例关系(在这里是:std::ratio<60*60>,表示一小时等于60分钟,一分钟等于60秒)// 所以, houre_type表示:以小时为单位的时长,可以用来定义变量,函数返回值等等。typedef std::chrono::duration<int,std::ratio<60*60>> hours_type;hours_type h_oneday(24);  // 24hstd::cout << h_oneday.count() << std::endl;seconds_type s_oneday(h_oneday);  // 86400sstd::cout << s_oneday.count() << std::endl;milliseconds_type ms_day(s_oneday);std::cout << ms_day.count() << std::endl;
}// 打印结果
24
86400
86400000

1.2 静态成员函数count

函数原型
constexpr rep count() const;
返回值
此duration 的计次数。std::cout << foo.count() * milliseconds::period::num / milliseconds::period::den;- 这是C++ 用来输出时间间隔的代码,其中 foo是 duration类型的一个变量- count() 用于获取foo的时间长度数量(计次数)- millisseconds::period::num 和 milliseconds::period::den- 是C++标准库中duration常量,-  milliseconds 时钟周期转换为浮点数表示的秒数。其中,milliseconds::period::num 表示时钟周期中每秒的计数,milliseconds::period::den 表示秒数的计数。- 通过除法运算可以得到每个时钟周期所表示的秒数。
#include<iostream>
#include<chrono>
int main()
{using namespace std::chrono;// std::chrono::milliseconds is an instatiation of std::chrono::durationmilliseconds foo(1000);  // 1 secondfoo*=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 duration_cast分析

将duration的值转换其他持续时间类型,同时也考虑它们之间的差异性。

Example
#include<iostream>
#include<chrono>
int main()
{std::chrono::seconds sec(1);  // 1sstd::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds> (sec);ms += std::chrono::milliseconds(2500); // 2500 millisecondsec = std::chrono::duration_cast<std::chrono::seconds>(ms);std::cout << "millseconds: " << ms.count() <<std::endl;std::cout << "senconds: " << sec.count() << std::endl;}打印结果
illseconds: 3500
senconds: 3

2:Time points

  • 它表示一个特定的时间点,比如一个人的生日,今天的黎明,或者下一班火车经过的时间点。
  • 在这个库中 :time_point 类模板的对象通过使用相对于 epoch的持续时间来表达这一点。
  • 相对于epoch 持续时间: 指的是一个特定的时间:1970-01-01 00:00:00 UTC
  • 在内部,该对象存储一个持续时间类型的对象,并使用Clock类型作为其 epoch的引用。
  • 💚💚💚
  • Importantly
  • A Clock class ,Such as system_clock steady_clock , high_resolution_clock or a custom clock

3:clocks

  1. 它是一种框架:一种将时间点与实际物理时间联系起来的矿建
  2. 此库提供了至少三个时钟,它们提供了将当前时间表示为时间点的方法:system_clock , steady_clock , high_resolution_clock

💚💚💚💚

  • system_clock:它所表现的 timepoint 将关联至现行系统的即时时钟(real-time clock), 这个clock 提供便捷函数 to_time_t() 和 from_time()_t()
  • steady_clock: 它保证绝不会被调整,因此当实际时间流逝,其 timepoint 值绝不会减少,而且这些 timepoint 相对于真实时间都有稳定的前进速率
  • high_resolution_clock : 它表现的是当前系统中带有最短 tick 周期 的clock .

案例 :

打印当前时间毫秒值,并转换成日历形式
1: 通过 system_clock::now() 获取 current time
2:定义一个 asString() 函数,它会将一个 以 system clock为依据的 timepoint 转换为 日历时间

#include<iostream>
#include<chrono>
#include<ctime>
int main()
{//std::chrono::system_clock::time_point tp;std::chrono::time_point<std::chrono::system_clock> tp;tp = std::chrono::system_clock::now();// tp = std::chrono::system_clock::time_point::max();// tp = std::chrono::system_clock::time_point::min();std::time_t t = std::chrono::system_clock::to_time_t(tp);std::cout <<"current time: "<< t ;std::string ts = std::ctime(&t);std::cout << "\\ncontain time zone(beijing time)\\n"<< ts;std::string ts1 = std::asctime(gmtime(&t));std::cout << "\\nUTC time\\n"<< ts1;std::string ts2 = std::asctime(localtime(&t));std::cout << "\\ncontain time zone(beijing time)\\n"<< ts2;}// 打印结果
current time: 1680700886
contain time zone(beijing time)
Wed Apr  5 21:21:26 2023UTC time
Wed Apr  5 13:21:26 2023contain time zone(beijing time)
Wed Apr  5 21:21:26 2023

🚀🚀🚀🚀🚀

几个问题需要说明

  1. std::chrono::time_point <std::chrono::system_clock > tp; 等价于 :std::chrono::system_clock::time_point tp;

但是你不能这么定义:std::chrono::time_point tp;
这样定义会报错 :no viable constructor or deduction guide for deduction of template arguments of ‘time_point’

  1. 将 timepoint 转换成 日历时间:

1:std::time_t time = std::chrono::system_clock::to_time_t(timepoint)
2:我们采用的是 static 函数 to_time_t() ,它会将 timepoint 转换为一个 “传统C和POSIX”提供的时间类型 time_t" 的对象,而那通常表型为 自UNIX epoch 起,亦即自 1970年1月1日起 开始计算的秒数
3:然后使用 ctime(& time) 转换成 一个 日历表示法。

  1. UTC 时间和 local 时间

1: std::ctime(&time) 和 std::asctime(localtime(&time)) 均表示 当地时间(即已经换算了时区)
2: std::asctime(gmtime(&t)) 表示 UTC 全球标准时间(没有换算时区)

实际应用

1:比较程序行两个时间点或计算其差距

// 定义起始时间
auto system_start = chrono::system_clock::now();
// 检查程序是否执行超过一分钟
if (std::chrono::system_clock::now() > system_start + std::chrono::minutes(1));

2:以计时器停滞线程 (Blocking with Timer)

1:Duration 和 timepoint 可用于线程或者程序(即主线程)的停滞(Block)。
2:停滞可以是无条件的,也可以是指定最大时间段,或等待一个 lock 或某条件成立,或等待另一个线程结束。

sleep_for()sleep_until(): 由 this_thread提供用以停滞线程
try_lock_for()try_lock_until():用来在等待一个 mutex时指定最大时间段
wait_for()wait_until():用来在等待某条件成立或等待一个 future时指定最大时间段。

Explame

// 停滞当前线程(也有可能是主线程)10s
std::this_thread::sleep_for(std::chrono::seconds(10))
// 停滞当前线程(也有可能是主线程),直到system clock 来到一个“比此刻多10s”的 timepoint
std::this_thread::sleep_until(std::chrono::system_clock::now()+ std::chrono::seconds(10));