std::chrono 库初探

std::chrono库初探

1. std::chrono库简介

std::chrono是C++11标准后,用于精度计时的时间库.

头文件写法#include <chrono>.

chrono不止是头文件的名称,也是子命名空间的名称. 除了common_type,该头文件中的全部元素不直接在std标准命名空间下定义,而是定义在std::chrono子命名空间之下.

2. std::chrono库主要概念

理解 std::chrono,需要抓住三个概念:分别是DurationTime pointsClocks.

  • Duration:表示的是一个时间跨度,如:一秒、两小时、十毫秒等. 在std::chrono库内,用Duration类模板的对象来表示这些时间跨度,如通过一个count和一个period的组合来表示“10ms”. “10”作为count表示时间的计数,“ms”作为period表示计时的精度.
  • Time points: 表示特定时间点,如一个人的生日、今天的黄昏,或者下一列火车经过的时刻. 在该库中,time_point类模板的实例化对象表达的是某个时间系统下经过一段时间后的时间点.
  • Clocks: 表示某个与真实物理时间点相关的时间系统. chrono库至少提供了三种时钟:分别是system_clock, steady_clock 和 high_resolution_clock.

3. std::chrono 之 Duration

3.1 std::chrono::duration

template <class Rep, class Period = ratio<1>> 
class duration;

一个duration对象通过一个count和一个period来表示一个时间段.

在内部,对象将count存储为成员类型rep的对象(第一个模板参数rep的别名),可以通过调用成员函数count来检索.

这个计数以period为单位表示。period周期的长度(在编译时)通过它的第二个模板参数(period)在类型中积分,这是一个ratio类型,表示在每个周期中花费的秒数(或分数).

构造方法举例:

// duration constructor
#include <iostream>
#include <ratio>
#include <chrono>

int main (int argc, char* argv[])
{
  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;

  system("pause");
  return 0;
}

输出结果为:

3600000ms in 1h

该例中注意,需要用到std::chrono::duration_cast函数对定义好的duration进行转换,才能用于不同duration间的定义.

3.2 模板参数

Rep

用作内部计数的类型的算术类型或模拟算术类型的类.

Period

表示以秒为单位的周期的ratio类型.

3.3 模板实例

duration中预定义的实例:

typeRepresentationPeriod
hours至少23位的有符号整型ratio<3600, 1>
minutes至少29位的有符号整型ratio<60, 1>
seconds至少35位的有符号整型ratio<1, 1>
milliseconds至少45位的有符号整型ratio<1, 1000>
microseconds至少55位的有符号整型ratio<1, 1000000>
nanoseconds至少64位的有符号整型ratio<1, 1000000000>

这里的ratio定义来自std::ratio库,可以参见小白的另一篇博客std::ratio初探

3.4 duration_cast转换函数

由于各种duration定义不同,chrono库提供了duration_cast类型转换函数

template <class ToDuration, class Rep, class Period>
  constexpr ToDuration duration_cast (const duration<Rep,Period>& dtn);

举例:

// duration_cast
#include <iostream>     // std::cout
#include <chrono>       // std::chrono::seconds, std::chrono::milliseconds
                        // std::chrono::duration_cast

int main ()
{
  std::chrono::seconds s (1);             // 1 second
  std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds> (s); // 转换成ms

  ms += std::chrono::milliseconds(2500);  // 2500 millisecond

  s = std::chrono::duration_cast<std::chrono::seconds> (ms);   // truncated 截断

  std::cout << "ms: " << ms.count() << std::endl;
  std::cout << "s: " << s.count() << std::endl;

  system("pause");
  return 0;
}

输出结果为:

ms: 3500
s: 3

3.5 duration::count函数

// duration::count
#include <iostream>     // std::cout
#include <chrono>       // std::chrono::seconds, std::chrono::milliseconds
                        // std::chrono::duration_cast

int main ()
{
  using namespace std::chrono;
  // std::chrono::milliseconds is an instatiation of std::chrono::duration:
  milliseconds foo (1000); // 1 second
  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";

  system("pause");
  return 0;
}

以上输出为

duration(in periods): 60000 milliseconds.
duration(in seconds): 60 seconds.

4. std::chrono 之 Time points

4.1 time_point 类模板定义

template <class Clock, class Duration = typename Clock::duration>
  class time_point;

time_point对象表示相对于时钟epoch的时间点.

在内部,对象存储一个duration类型的对象,并使用Clock类型作为其epoch的引用.

4.2 time_point 类的构造函数

(1)	time_point();
(2)	template <class Duration2>
time_point (const time_point<clock,Duration2>& tp);
(3)	explicit time_point (const duration& dtn);

三种构造形式

// time_point constructors
#include <iostream>
#include <chrono>
#include <ctime>

int main ()
{
  using namespace std::chrono;

  system_clock::time_point tp_epoch;	// epoch value

  time_point <system_clock,duration<int>> tp_seconds (duration<int>(1));

  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;

  // display time_point:
  std::time_t tt = system_clock::to_time_t(tp);
  std::cout << "time_point tp is: " << ctime(&tt);
  
  system("pause");
  return 0;
}

输出为

1 second since system_clock epoch = 1000000 system_clock periods.
time_point tp is: Thu Jan 01 01:00:01 1970

4.3 time_since_epoch函数

表示自某个epoch时间之后,到某个time_point之间,总共过了多少的时间.

// time_point::time_since_epoch
#include <iostream>
#include <chrono>

int main ()
{
  using namespace std::chrono;

  system_clock::time_point tp = system_clock::now();
  system_clock::duration dtn = tp.time_since_epoch();

  std::cout << "current time since epoch, expressed in:" << std::endl;
  std::cout << "periods: " << dtn.count() << std::endl;
  std::cout << "seconds: " << dtn.count() * system_clock::period::num / system_clock::period::den;
  std::cout << std::endl;

  return 0;
}

输出结果为

current time since epoch, expressed in:
periods: 16438059145690158
seconds: 1643805914

4.4 time_point_cast函数

template <class ToDuration, class Clock, class Duration>
  time_point<Clock,ToDuration> time_point_cast (const time_point<Clock,Duration>& tp);

将tp的值转换为具有不同持续时间内部对象的time_point类型,并考虑它们持续时间的周期差异.

该函数使用duration_cast转换内部duration对象.

注意,函数的第一个模板形参不是返回类型,而是它的duration组件.

示例程序为:

// time_point_cast
#include <iostream>
#include <ratio>
#include <chrono>

int main ()
{
  using namespace std::chrono;

  typedef duration<int,std::ratio<60*60*24>> days_type;

  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;
}

输出结果为

19025 days since epoch

注意这个程序中,是把默认的秒转换成了天数.

5. std::chrono 之 Clocks

提供的系统时钟总共有三种,分别为system_clock、steady_clock、high_resolution_clock.

5.1 system_clock

系统时钟,常用.

提供一种能够取到当前时间点的时钟.

具体来说,它是一个系统范围内的实时时钟.

它有三个成员函数,分别是now、to_time_t、from_time_t

  • now: 取当前的时间
  • 转换到time_t的时间
  • 从time_t的时间进行转换
// system_clock example
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>

int main ()
{
  using std::chrono::system_clock;

  std::chrono::duration<int,std::ratio<60*60*24> > one_day (1);

  system_clock::time_point today = system_clock::now();
  system_clock::time_point tomorrow = today + one_day;

  std::time_t tt;

  tt = system_clock::to_time_t ( today );
  std::cout << "today is: " << ctime(&tt);

  tt = system_clock::to_time_t ( tomorrow );
  std::cout << "tomorrow will be: " << ctime(&tt);

  return 0;
}

输出结果为:

today is: Wed Feb 02 21:08:41 2022
tomorrow will be: Thu Feb 03 21:08:41 2022

5.2 steady_clock

这个系统时钟的特性,在任意两次调用时,后一次调用的结果一定不小于前一次调用.

这个系统时钟专为计时而设计.

它有一个成员函数为now,用以获取调用时的时间.

// steady_clock example
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>

int main ()
{
  using namespace std::chrono;

  steady_clock::time_point t1 = steady_clock::now();

  std::cout << "printing out 1000 stars...\n";
  for (int i=0; i<1000; ++i) std::cout << "*";
  std::cout << std::endl;

  steady_clock::time_point t2 = steady_clock::now();

  duration<double> time_span = duration_cast<duration<double>>(t2 - t1);

  std::cout << "It took me " << time_span.count() << " seconds.";
  std::cout << std::endl;

  return 0;
}

输出结果为:

printing out 1000 stars...
****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
It took me 0.0699535 seconds.

5.3 high_resolution_clock

时钟类的成员提供对当前time_point的访问。

High_resolution_clock是tick周期最短的时钟。它可以是system_clock或steady_clock的同义词。

理论上可以提供系统最高精度的计时,与前二者的用法类似,这里不做更多解释.

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值