C++11 chrono入门

原创 2017年06月17日 20:54:18

​    C++11引入chrono类来表示时间中的一些概念,以及进行时间相关的计算,这是因为传统使用算术的方式来表示时间间隔和时间点本身这是很模凌两可的。通过使用chrono类库,使用不同的类型来表示不同的时间概念,这有助于通过编译器在编译时来帮助程序员发现一些逻辑错误,为此chrono抽象了如下几个概念:

duration

​    一个时间的duration表示的就是一个时间间隔,比如:3秒、3分钟、3小时等。在chrono类库中就分别有对应的时间单位来表示durationstd::chrono::seconds表示的是秒,是时间的间隔单位,其实现如下:

class seconds {
   int64_t sec_;
  public:
   seconds() = default;
   //....
};

​    就是一个类中包含了一个int64_t的成员来保存秒数,很简单,其次为了区分秒数和普通的数值之间的差异,seconds类在设计的时候就禁止数值隐式转换为seconds类,所以下面这样的操作编译不会通过:

seconds s = 3;  // 编译出错
seconds s1{3};  // 这样是可以的
s1 = 4; // 编译出错

std::cout << s << "\n"; // 很不幸目前还不可以
std::cout << s.count() << "s\n"; // 这样是可以的

seconds s2 = 3s;    // C++14支持
seconds s3 = s2 + s1;   // 支持基本的算术操作,但是不支持seconds和一个普通数值进行算术操作

seconds::min(); // 获取秒类型可以表示的范围,
seconds::max();

​    除了seconds外,chrono还提供了nanosecondsmicrosecondsmillisecondsminuteshours。用法基本上seconds一致。这些类型之间的转化规则chrono都已经帮我们做好了,例如: 1seconds == 1000milliseconds,而且这种转换是隐式的。例如下面这段代码:

minutes s1{2};
seconds s2 = s1;        // s1隐式转换为seconds
seconds s3 = s2 + s1;   // s1隐式转换为seconds,然后运算  

​    但是这种转换有一个前提就是,转换必须时向下转换,比如hours转换minutesminutesseconds等,如果想向上转换就需要使用duration_cast显式的进行转换,例如下面这段代码:

seconds s2{1000};
minutes s3 = duration_cast<minutes>(s2);    

​    chrono虽然已经内置了大多数的时间单位,但是它也提供了自定义类型的方法,你可以通过这个方法自定义出另外一种新的时间单位,你也可以定制你的时间单位的内部存储,默认的chrono提供的时间单位都是使用64位大小的存储,如果你想使用32位的存储你也可以进行定制,定制的方法如下:

using seconds32 = std::chrono::duration<int32_t>;   // 使用32位来表示seconds
using new_type = std::chrono::duration<int64_t>;    // 自定义新的new_type单位
using float_type = std::chrono::duration<float>;    // 支持浮点数的新单位

​    默认提供的时间单位都是整型的,通过上面的办法你甚至可以自定义出支持浮点数的时间单位,只需要设置其类型为double或者float即可。虽然通过上面的方法可以对时间单位进行定制了,但是如何自定义该单位和其他时间单位的转换规则呢?默认的时间单位都有默认的转换规则。这个时候chrono提供了另外一个新的概念ratio,通过这个概念来决定转换的规则。

ratio

​    ration对应到时间单位的转换比例,是一个模版,提供了两个模版参数,默认提供好一系列的模版实例:

  typedef ratio<1,       1000000000000000000> atto;
  typedef ratio<1,          1000000000000000> femto;
  typedef ratio<1,             1000000000000> pico;
  typedef ratio<1,                1000000000> nano;
  typedef ratio<1,                   1000000> micro;
  typedef ratio<1,                      1000> milli;
  typedef ratio<1,                       100> centi;
  typedef ratio<1,                        10> deci;
  typedef ratio<                       10, 1> deca;
  typedef ratio<                      100, 1> hecto;
  typedef ratio<                     1000, 1> kilo;
  typedef ratio<                  1000000, 1> mega;
  typedef ratio<               1000000000, 1> giga;
  typedef ratio<            1000000000000, 1> tera;
  typedef ratio<         1000000000000000, 1> peta;
  typedef ratio<      1000000000000000000, 1> exa;

​    至于为什么secondsmilliseconds为什么可以相互转换,这是因为它们在创建的时候就已经设置好了默认的转换规则,还记得上文中的duration吗?可以用来自定义时间间隔单位,默认的secondsmilliseconds等就是通过std::chrono::duration创建的,代码如下:

using nanoseconds  = duration<int_least64_t,    nano>
using microseconds = duration<int_least55_t,    micro>
using milliseconds = duration<int_least45_t,    milli>
using seconds = duration<int_least35_t, ration<1>>
using minutes = duration<int_least29_t, ration<60>>
using hours = duration<int_least23_t, ration<3600>>


template <class Rep, class Period = ratio<1>>
class duration {
public:
    using rep = Rep;
    using period = Period;
// ...  };

​    通过上面的代码可以看出,默认的时间间隔单位都带有一个时间转换比例,是通过duration模版类的第二个参数设置的,因此如果想给自定义的时间间隔单位设置转换比例,就可以具现化一个ratio类,然后传给duration即可。

time point

​    无论是生活中,还是在程序编码的时候,光一个时间间隔是不够的,我们常常需要具体的时间点,比如:2017年12月21日10时50封23秒,对于这样的概念,chrono库使用time_point来表示,这是一个模版类,其实现如下:

template <class Clock,
          class Duration = typename Clock::duration>
class time_point {
    Duration d_;
public:
    using clock    = Clock;
    using duration = Duration;
// ...  };

​    有两个模版参数,第一个是使用何种时钟,第二个是时间间隔,可见时间点的底层是用的duration来存储的,那么很自然两者也是可以相互进行转换的,通过time_pointtime_since_epoch方法就可以将一个时间点,转换为时间间隔。和时间间隔一样,不同类型的时间点之间也可以相互转换,默认是隐式的向下转换,如果想向上转换就必须显示的使用time_point_cast来进行转换,代码如下:

  using namespace std::chrono;
  template <class D>
    using sys_time = time_point<system_clock, D>;
  sys_time<seconds> tp{5s};            // 5s
  sys_time<milliseconds> tp2 = tp;     // 5000ms  隐式的向下转换
  tp = time_point_cast<seconds>(tp2);  // 5s  向下转换,需要显示的使用time_point_cast

clocks

​    最后讨论下时钟的概念,在讨论time point的时候就谈到过时钟,说简单点时钟就是时间点,时间间隔以及一顿静态方法的集合。它的实现可以简单的表示为下面这种形式:

struct some_clock
{
    using duration = chrono::duration<int64_t, microseconds>;
    using rep = duration::rep;
    using period = duration::period;
    using time_point = chrono::time_point<some_clock>; 
    static constexpr bool is_steady = false; 
     static time_point now() noexcept;
};

​    每一个时间点都关联了一个时钟,不同时钟的时间点事没有办法相互转换的,代码如下:

system_clock::time_point tp = system_clock::now();
steady_clock::time_point tp2 = tp;  // no viable conversion

​    默认系统提供了两张时钟,一个就是system_clock,另外一个则是steady_clock ,前者表示的就是墙上时钟,和挂在墙上的时钟保持一样,但是这个值并不一定是单调的,因为操作系统可能会修改时间,导致system_clock返回的时间不单调。而steady_clock表示的是单调时钟,随着物理时间向前,这个时钟的时间点不会减少,因为该时钟与墙上的挂钟时间无关,最适合进行间隔的测量。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C++11的chrono库,可实现毫秒微秒级定时

C++11有了chro #include usingnamespace std; usingnamespace std::chrono;   cl...

[cpp]C++11学习笔记-chrono

chrono是一个时间库,提供有时间段,时间点,系统时钟相关功能。

C++11 std::chrono库详解

chrono是一个time library, 源于boost,现在已经是C++标准, 今天我们一起来看看它的用法。   要使用chrono库,需要#include,其所有实现均在std::chr...

C++11中的便利工具--chrono库(处理日期和时间)

chrono is the name of a header, but also of a sub-namespace: All the elements in this header (except...

c++11 Chrono时间库

c++11 Chrono时间库http://en.cppreference.com/mwiki/index.php?title=Special%3ASearch&search=chrono1. 持续时...

c++11之chrono头文件

今天看了下chrono,莫名的想翻译一下,望大家指点,小白翻译  头文件    时间库      chrono是一个头文件的名字,但是也是一个std下的一个子命名空间的名字:在这个头文件下的所有元素(...

分享C++11代码片段-tuple和chrono

元组,我也不清楚,c++是不是借鉴了python从而引入了元组。tuple元组定义了一个有固定数目元素的容器,其中的每个元素类型都可以不相同,这与其他容器有着本质的区别.是对pair的泛化。首先来介绍...

c++11知识点3_chrono时间模板库

1.概述 chrono是一个time library, 源于boost,现在已经是C++11标准。 要使用chrono库,需要#include,其所有实现均在std::chrono namespa...

C++11标准库chrono

chrono是C++11新加入的方便时间日期操作的标准库,它既是相应的头文件名称,也是std命名空间下的一个子命名空间,所有时间日期相关定义均在std::chrono命名空间下。通过这个新的标准库,可...

c++11正则表达式入门

#include #include #include #include namespace std { typedef basic_regex wregex; } int main() ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++11 chrono入门
举报原因:
原因补充:

(最多只允许输入30个字)