C/C++编程:chrono库学习

1059 篇文章 286 订阅

引入

  • 在过去,C和POSIX提供的系统时间接口,允许从秒转换至毫秒,再至微秒,最终至纳秒,问题是每次转换就需要一个新接口
  • 基于这个原因,C++11开始提供一个精度中立的程序库,称为chrono程序库,被定义于<chrono>中

 

概述

  • Chrono程序库的设计,是希望能够处理“timer和clock在不同系统中可能不同”的事实,同时也是为了强化实践精准度
  • 为了避免像POSIX的time程序库那样每十年就引入一个新的时间类型,C++标准库的目标是提供一个精度中立概念,把duration(时间段)和timepoint(时间点)从特定clock(时钟)区分开来。最终结果就是chrono程序库核心由以下类型或概念组成:
  • Chrono程序库定义在<chrono>头文件中,命名空间为namespace std::chrono

 

Duration

辅助类型

 

构造函数

#include <chrono>
int main()
{
   // 方法1:手动指定单位(基本不用)
    std::chrono::duration<int>                       twentySeconds(20);  // 20*1秒=20秒(以秒为单位)
    std::chrono::duration<double, std::ratio<60>>    halfAMinute(0.5);   // 0.5*60秒=0.5分钟(以分钟为单位(60/1))
    std::chrono::duration<long, std::ratio<1, 1000>> oneMillisecond(1);  //1*0.001秒=1毫秒(以毫秒为单位(1/1000))



    // 内置定义
   std::chrono::seconds      twentySeconds(20); //20秒
   std::chrono::hours        aDay(24);          //24小时
   std::chrono::milliseconds oneMillisecond(1); //1毫秒
 
    // 错误: treat_as_floating_point<int>::value == false,
    // 此时长只允许整数计次
//  std::chrono::duration<int, std::kilo> d3(3.5);
 
    // 使用小数计次的 30Hz 钟
    std::chrono::duration<double, std::ratio<1, 30>> hz30(3.5);
 
    // 从 3 毫秒构造 3000 微秒
    std::chrono::microseconds us = ms;
    // error: 1/1000000 is not divisible by 1/1000
//  std::chrono::milliseconds ms2 = us
    std::chrono::duration<double, std::milli> ms2 = us; // 3.0 毫秒
}

 

count

作用:返回此 duration 的嘀嗒数。

#include <chrono>
#include <iostream>
int main()
{
    std::chrono::milliseconds ms{3}; // 3 毫秒
    // 从 3 毫秒构造 6000 微秒
    std::chrono::microseconds us = 2*ms;
    // 使用分数计次的 30Hz 时钟
    std::chrono::duration<double, std::ratio<1, 30>> hz30(3.5);
 
    std::cout <<  "3 ms duration has " << ms.count() << " ticks\n"
              <<  "6000 us duration has " << us.count() << " ticks\n"
              <<  "3.5 30Hz duration has " << hz30.count() << " ticks\n";       
}

 

运算

运算所涉及的两个duration的单位类型可以不同,返回值单位将是两个操作数的单位的最大公约数

  • 演示案例:
std::chrono::seconds      d1(42); //42秒
std::chrono::milliseconds d2(10); //10毫秒
 
d1 - d2; //返回41990个毫秒为单位的一个duration,42000-10=41990
d1 < d2; //返回false
  • 演示案例:
std::chrono::duration<int, std::ratio<1, 3>> d1(1); //1/3秒
std::chrono::duration<int, std::ratio<1, 5>> d2(1); //1/5秒
 
d1 + d2; //返回8/15秒,1/3+1/5=8/15
d1 < d2; //返回false
  • 你也可以将duration转换为不同的单位,只要彼此之间存在隐式转换即可。因此,你可以将小时转换为秒,但是反向不可以(详情还可以见duration_cast<>()的介绍)。例如:
std::chrono::seconds twentySeconds(20); //20分钟
std::chrono::hours   aDay(24);          //24消失
 
std::chrono::milliseconds ms;           //0毫秒
ms += twentySeconds + aDay;             //86400000毫秒
--ms;                                   //86399999毫秒
ms *= 2;                                //172839998毫秒
 
std::cout << ms.count() << " ms" << std::endl;   // 172839998ms
std::cout << std::chrono::nanoseconds(ms).count() << " ns" << std::endl;  //172839998000000 ns
  • 演示案例:
template<typename V,typename R>
std::ostream& operator<<(std::ostream& s, const std::chrono::duration<V, R>& d)
{
    s << "[" << d.count() << " of " << R::num << "/" << R::den << "]";
    return s;
}
 
int main()
{
    std::chrono::milliseconds d(42);
    std::cout << d << std::endl;

 

 

 

duration_cast

  • 在上面我们介绍过duration的类型转换,可以将一个低精度的单位类型转换为一个高精度的单位类型(例如,将分钟转换为秒,将秒转换为微秒),但是不能将一个高精度的单位类型转换为一个低精度的单位类型(例如,将微秒转换为秒,将秒转换为分钟等。因为这可能会造成数据的丢失,例如将42010毫秒转换为秒,结果是42,那么原本的10毫秒就丢失了)
  • 如果想要将高精度的单位类型转换为一个低精度的单位类型,那么可以使用duration_cast<>进行强制转换
std::chrono::seconds sec(55);
 
//错误的,默认不能将秒转换为分钟
std::chrono::minutes m1 = sec;
 
//正确的,可以使用duration_cast,将秒转换为分钟
std::chrono::minutes m2 = std::chrono::duration_cast<std::chrono::minutes>(sec);
  • 将浮点数类型的duration转换为整数类型的duration也需要使用duration_cast<>。例如:
std::chrono::duration<double, std::ratio<60>> halfMin(0.5);
 
//错误,halfMin的tick为double类型,s1的tick默认为int类型
std::chrono::seconds s1 = halfMin;
 
//正确,使用duration_cast强制转换
std::chrono::seconds s2 = std::chrono::duration_cast<std::chrono::seconds>(halfMin);

 

  • 演示案例:
#include <iostream>
#include <chrono>
#include <ratio>
#include <thread>
 
void f()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    auto t1 = std::chrono::high_resolution_clock::now();
    f();
    auto t2 = std::chrono::high_resolution_clock::now();
 
    // 整数时长:要求 duration_cast
    auto int_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
 
    // 小数时长:不要求 duration_cast
    std::chrono::duration<double, std::milli> fp_ms = t2 - t1;
 
    std::cout << "f() took " << fp_ms.count() << " ms, "
              << "or " << int_ms.count() << " whole milliseconds\n";
}

 

 

#include <chrono>
#include <iostream>
int main()
{
    // 简单算术
    std::chrono::seconds s = std::chrono::hours(1) 
                             + 2*std::chrono::minutes(10)
                             + std::chrono::seconds(70)/10;
 
    std::cout << "1 hour + 2*10 min + 70/10 sec = " << s.count() << " seconds\n";
 
    // 时长除以一个数和时长除以另一时长的区别
    std::cout << "Dividing that by 2 minutes gives "
              << s / std::chrono::minutes(2) << '\n';
    std::cout << "Dividing that by 2 gives "
              << (s / 2).count() << " seconds\n";
 
   // 余数运算符在确定此特定时长在时间框架的场合有用,
   // 例如,拆分它为时、分和秒:
   std::cout << s.count() << " seconds is "
             << std::chrono::duration_cast<std::chrono::hours>(s).count() << " hours, "
             << std::chrono::duration_cast<std::chrono::minutes>(s % std::chrono::hours(1)).count() << " minutes, "
             << std::chrono::duration_cast<std::chrono::seconds>(s % std::chrono::minutes(1)).count() << " seconds\n";
}

比较大小

#include <chrono>
#include <iostream>
int main()
{
    if(std::chrono::seconds(2) == std::chrono::milliseconds(2000))
        std::cout <<  "2 s == 2000 ms\n";
    else
        std::cout <<  "2 s != 2000 ms\n";
 
    if(std::chrono::seconds(61) > std::chrono::minutes(1))
        std::cout <<  "61 s > 1 min\n";
    else
        std::cout <<  "61 s <= 1 min\n";
 
}

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值