欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c11 chrono详解

程序员文章站 2022-07-14 08:07:22
...

转自:https://blog.csdn.net/hou8389846/article/details/77962343#commentBox

chrono是c++11的时间库,提供计时,时钟等功能。
了解chrono,主要了解时间段(duration)和时间点(time_point)的概念。

1、精度(ratio)

时钟节拍(时间精度):

template<intmax_t N, intmax_t D = 1> class ratio;

其中N表示分子(对应period::num),D表示分母(默认用秒表示的时间单位,对应period::den)。
常用的单位:

ratio<3600, 1> hours;
ratio<60, 1> minutes;
ratio<1, 1> seconds;
ration<1, 1000> milliseconds;

test:

#include <iostream>
#include <chrono>
using namespace std;
int main(int argc, char *argv[])
{
    cout << "milliseconds = ";
    cout << std::chrono::milliseconds::period::num << "/" \
         << std::chrono::milliseconds::period::den << "s" << endl; //out: 1/1000s

    typedef std::chrono::duration<int, std::ratio<1, 2> > halfseconds;

    cout << "halfseconds = ";
    cout << halfseconds::period::num << "/" \
         << halfseconds::period::den << "s" << endl; //out: 1/2s

    cout << "microseconds = ";
    cout << std::chrono::microseconds::period::num << "/" \
         << std::chrono::microseconds::period::den << "s" << endl; //out: 1/1000000s
    return 0;
 }

2、时间段(duration)

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

std::chrono::duration(时间段)表示一段时间,如半个小时,12.88秒,半天,一炷香的时间等等。

Rep表示一种数值类型,用来表示Period数量。如:int,float, double;
Period是ratio类型,用来表示时间精度。如:hours,seconds,minutes等;

chrono中宏定义了很多特例化的duration:

typedef std::chrono::duration<int64_t> seconds;
typedef std::chrono::duration<int64_t, ratio<60> >	munites;
typedef std::chrono::duration<int64_t, ratio<3600> > hours;
typedef std::chrono::duration<int64_t, ratio<1, 1000> >	milliseconds;

构造函数

duration() = default;

duration(const duration& dtn);

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

template<class Rep>
constexpr duration(const Rep & rep);

成员函数count()显示单位时间的数量

example:

#include <chrono>
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{

    cout << "microseconds = ";
    cout << std::chrono::microseconds::period::num << "/" \
         << std::chrono::microseconds::period::den << "s" << endl;

    typedef std::chrono::duration<int64_t, ratio<1, 2> > halfseconds;

    halfseconds halfsec(1000);
    cout << halfsec.count() << endl; //out: 1000
    cout << "halfsec(1000) = " << halfsec.count()*halfseconds::period::num/ \
            halfseconds::period::den << "s" << endl; //out: 500s

    std::chrono::milliseconds ms(2000);
    cout << ms.count() << endl; //out: 2000
    cout << "milliseconds(2000) = " << halfsec.count()* \
            std::chrono::milliseconds::period::num/ \
            std::chrono::milliseconds::period::den << "s" << endl; //out: 1s

    return 0;
}

时间段的显示转换由std::chrono::duration_cast<> 来实现。

std::chrono::milliseconds ms(54800);
std::chrono::seconds sec = std::chrono::duration_cast<std::chrono::seconds>(ms);//out:sec = 54S

3、时间点(time_point)

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

std::chrono::time_point表示一个具体时间(能用计算机时间表示),如:今天下午3点,火车出发时间等等。
模板第一个参数Clock指定所有的时钟(标准库中有三种时钟:system_clock、steady_clock和high_resulotion_clock),第二个参数表示时间的计量单位(特化std::chrono::duration<>)。
时间点都有一个时间戳,即时间原点。chrono库中采用的是Unix的时间戳1970年1月1日 00:00。所以time_point也就是距离时间戳(epoch)的时间长度(duration)。

构造函数

time_point() = default;//默认构造函数

template<class Duration2>
time_point(const time_point<clock, Duration2> &tp); //拷贝构造函数

explicit time_point(const duration &dtn);//用duration来构造,就是距离时间戳的长度

duration time_since_epoch()

此函数表示当前时间距离时间戳的时间长度,即当前时间点到时间戳(1970年1月1日 00:00)的时间距离,返回duration的精度与构造time_point的Clock有关。
test

#include <chrono>
#include <iostream>
#include <ctime>
using namespace std;

int main(int argc, char *argv[])
{
    using namespace std::chrono;
    time_point<system_clock, seconds> tp(seconds(2));
    cout << "time_since_epoch = " << tp.time_since_epoch().count() << endl;

    //转换成ctime,打印时间点
    time_t tt = system_clock::to_time_t(tp);
    char a[50] = {0};
    ctime_s(a, 50, &tt);
    cout << a << endl;//out:Thu Jan 01 08:00:02 1970
    
    return 0;
}

4、时钟(当前系统时间)

chrono中包含三种系统时钟:system_clock、steady_clock、high_resolution_clock。每一个clock类都有确定的time_point、duration、Rep和Period类型。
system_clock是不稳定的。因为时钟是可调的,即这种是完全自动适应本地账户的调节。这种调节可能造成的是,首次调用now()返回的时间要早于上次调用now()所返回的时间,这就违反了节拍频率的均匀分布。稳定闹钟对于超时的计算很重要,所以C++标准库提供一个稳定时钟 std::chrono::steady_clock。std::chrono::high_resolution_clock 是标准库中提供的具有最小节拍周期(因此具有最高的精度的时钟)。
time_since_epoch()和now()的返回值都依赖于时钟的精度。检测精度的方法:

#include <chrono>
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    using namespace std::chrono;
    cout << "system clock:  " \
         << system_clock::period::num << "/" << \
            system_clock::period::den << "s" << endl; //out:1/1000000000(1ns)

    cout << "steady clock:  " \
         << steady_clock::period::num << "/" << \
            steady_clock::period::den << "s" << endl; //out:1/1000000000(1ns)

    cout << "high resolution clock:  " \
         << high_resolution_clock::period::num << "/" << \
            high_resolution_clock::period::den << "s" << endl; //out:1/1000000000(1ns)

    return 0;
}

成员函数

 //获取当前系统时间
static time_point now() noexcept;

//time_point的转换函数
template<class ToDuration, class Clock, class Duration>
time_point<Clock, ToDuration> time_point_cast(const time_point<Clock,Duration> &tp);

//time_point转换成ctime(秒)
to_time_t()

//ctime转换成time_point
from_time_t()

综合应用

输出当前时间,并且计算当前的时间距离1970年1月1日00:00的毫秒数,计算两个时间的时间长度。

#include <chrono>
#include <iostream>
#include <ctime>
using namespace std;

int main(int argc, char *argv[])
{
    using namespace std::chrono;

    //显示当前系统时间及距离时间戳的时间长度(秒)
    typedef chrono::time_point<chrono::system_clock, chrono::seconds> secClock;
    secClock sec = chrono::time_point_cast<chrono::seconds>(chrono::system_clock::now());

    time_t tt =  system_clock::to_time_t(sec);

    char a[50];
    ctime_s(a, sizeof (a), &tt);
    cout << "time now[s] : " << a;

    cout << "to 1970-1-1,00:00[s]  " << sec.time_since_epoch().count() << "s" << endl;

    for(unsigned int i = 0; i < 1000000000; ++i) {
        if(i%10000000 == 0) {
            cout << "*";
        }
    }
    cout << endl;

    //显示当前系统时间及距离时间戳的时间长度(毫秒)
    typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> milliClock;
    milliClock ms = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());

    time_t mt = chrono::system_clock::to_time_t(ms);

    char cmt[50] = {0};
    ctime_s(cmt, sizeof (cmt), &mt);
    cout << "now time[ms] = " << cmt;

    cout << "to 1970-1-1,00:00[ms]  " << ms.time_since_epoch().count() << "ms" << endl;


    //计算两个时间的时间长度[秒级]
    cout << "from sec to ms :" << (chrono::time_point_cast<chrono::seconds>(ms) - sec).count() << endl;

    return 0;
}