std::chrono库初探
文章目录
1. std::chrono库简介
std::chrono是C++11标准后,用于精度计时的时间库.
头文件写法#include <chrono>
.
chrono不止是头文件的名称,也是子命名空间的名称. 除了common_type
,该头文件中的全部元素不直接在std标准命名空间下定义,而是定义在std::chrono子命名空间之下.
2. std::chrono库主要概念
理解 std::chrono,需要抓住三个概念:分别是Duration、Time points、Clocks.
- 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中预定义的实例:
type | Representation | Period |
---|---|---|
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的同义词。
理论上可以提供系统最高精度的计时,与前二者的用法类似,这里不做更多解释.