C++11標准庫chrono庫使用


chrono是C++11新加入的方便時間日期操作的標准庫,它既是相應的頭文件名稱,也是std命名空間下的一個子命名空間,所有時間日期相關定義均在std::chrono命名空間下。通過這個新的標准庫,可以非常方便進行時間日期相關操作。
chrono庫主要包含了三種類型:duration, time_point 和 clock。

Duration(時間間隔)

chrono庫中用一個duration模板類,用來表示一段時間間隔,可以表示幾秒鍾、幾分鍾或者幾個小時的時間間隔。

原型

template<typename _Rep, typename _Period = ratio<1>>
struct duration
{
typedef _Rep   rep;
...
private:
    rep  __r;  //內部維護的計數個數成員
...
};

第一個模版參數是數值類型,表示時鍾個數;第二個為std::ratio,用來表示每個時鍾的周期(單位為秒)
ratio的原型是

template<intmax_t _Num, intmax_t _Den = 1>
struct ratio;

這是一個非類型模版參數的模版類,intmax_t是定義在cstdint頭文件中的內置類型。第一個參數代表分子,第二個代表分母,兩者表示一個通用的比率類型。它們必須在編譯期間確定為常量值。分母默認為1,因此ratio<60>代表60,ratio<1, 1000>代表0.001。為了方便使用,在ratio頭文件中定義了常用比率的別名:

  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;

回到duration模板類,默認的比率為ratio<1>,也就是一個時鍾數_Rep代表1秒。為了方便使用,chrono庫定義了如下的常用時間單位:

/// nanoseconds
typedef duration<int64_t, nano>     nanoseconds;

/// microseconds
typedef duration<int64_t, micro>    microseconds;

/// milliseconds
typedef duration<int64_t, milli>    milliseconds;

/// seconds
typedef duration<int64_t>       seconds;

/// minutes
typedef duration<int, ratio< 60>>   minutes;

/// hours
typedef duration<int, ratio<3600>>  hours;

通過定義上述常用類型,可以非常方便的使用:

//線程休眠10秒
std::this_thread::sleep_for(std::chrono::seconds(10));

成員

duration內部維護了周期個數rep和周期period,兩者結合用來表示間隔時間。

count

用來獲取內部維護的rep類型的周期個數,或稱為tick數。即定義變量的實參

chrono::milliseconds ms(10);//10個tick
chrono::duration<double, std::ratio<1, 30>> dur(10.5);//10.5 tick
cout << "ms: " << ms.count() << '\t' << "dur: "<< dur.count() << endl;

上述代碼輸出:

ms: 10 dur : 10.5

靜態成員函數

duration實例化后,對於給定的rep表示周期個數的類型,提供了min、max和zero三個靜態成員函數,用來獲取當前類型能表示的最小、最大周期數和0周期數代表的duration對象。

cout << chrono::seconds::max().count() << endl;

//輸出結果為:9223372036854775807

運算操作

duration支持基本所有算術運算操作,而且不同單位之間的可以自動進行匹配。這是通過duration_cast模板類實現的。

chrono::minutes t1(5);
chrono::seconds t2(30);
chrono::seconds t3 = t1 - t2;
cout << t3.count() << '\t' << chrono::duration_cast<chrono::minutes>(t3).count() << endl;

//對於類型轉換會進行舍入
//輸出結果:270 4

Time point

chrono庫中用一個time_point模板類,表示一個時間點,如生日、今天日落時刻等,通過一個相對epoch的時間間隔duration來實現,epoch就是1970-1-1時刻,對於同一個時鍾來說,所有的time_point的epoch都是固定的。這個類可以與標准庫ctime結合起來顯示時間,ctime內部的time_t類型就是代表這個秒數。

原型

template<typename _Clock, typename _Dur = typename _Clock::duration>
struct time_point
{
typedef _Clock                      clock;
typedef _Dur                        duration;
typedef typename duration::rep              rep;
typedef typename duration::period           period;
private:
    duration __d; //維護的內部duration成員
...

};

第一個參數為當前計時使用的時鍾,可選為“system_colck”、“steady_colck”、“high_resolution_clock”或者是自定義的時鍾類;
第二個參數為時間間隔,默認為使用的時鍾相同的間隔。
內部維護了一個duration私有成員,通過制定的時鍾,來確定距離epoch時間點的間隔。

成員

chrono::time_point<system_clock> tp = chrono::system_clock::now();
cout << tp.time_since_epoch().count() << endl;

//輸出為:1452672734311762303
//system_clock的ratio為nano

運算

與duration類似,time_point也提供了靜態成員min和max,以及算術運算操作,這些都是通過內部維護的duration成員進行的,duration成員的各種操作由前面所述的提供保障,time_point就只需要通過time_since_epoch獲取私有duration成員進行調用即可。還提供了與duration直接進行”+=”和“-=”的運算操作,對於普通的算術運算,如果有一個操作數類型為duration,則是在time_point類型操作數內部維護的duration成員上進行操作,則返回類型為time_point;當兩者均為time_point類型時,返回類型為二者維護的duration成員之差,從而返回類型也為duration。

表示當前系統時鍾,共有三種:

  • system_clock:從系統獲取時鍾
  • steady_clock:不能被修改的時鍾
  • high_resolution_clock:高精度時鍾,實際上是system_clock或者steady_clock的別名,最小精度是納秒

system_clock

system_clock 提供三個靜態的函數,可以用於time_point提供了與C API的時間交互的良好定義。因此,可以很容易與time_t類型打交道。接口函數如下:

//get current time
static time_point now() noexcept;

//time_point conver to time_t
static time_t to_time_t (const time_point& tp) noexcept;

//convert time_t to time_oint
std::chrono::system_clock::from_time_t
static time_point from_time_t (time_t t) noexcept;

system_clock 和ctime函數使用demo:


#include <iostream>
#include <ctime>
#include <chrono>

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

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

    //current time
    system_clock::time_point today = system_clock::now();

    //tomorrow time
    system_clock::time_point tomorrow = today + one_day;

    //convert time type   
    time_t tmTomorrow = system_clock::to_time_t ( tomorrow );

    //time string
    std::cout << "tomorrow will be: " << ctime(&tmTomorrow);

    struct tm *p;   
    p = localtime(&tmTomorrow); /*轉換為struct tm結構的當地時間*/  
    printf("%d/%d/%d ", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday); 

    return 0;
}

運行結果:

tomorrow will be: Sun Feb 11 09:13:07 2018
2018/2/11 

steady_clock

steady_clock 專門用於計算時間差的工具,steady_clock 類只有一個靜態函數now(),用於獲取當前的時間,計算時間差的方式如下:

#include <iostream>
#include <chrono>

int main()
{
    typedef std::chrono::steady_clock  STEADY_CLOCK;

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

    std::cout << "print 1000 stars" << std::endl;

    for (int i=1; i<=1000; ++i)
    {
        std::cout << "*";
        if (0 == i % 50) 
        {
            std::cout << "\n";
        }
    }

    std::cout << std::endl;

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

    //毫秒
    std::chrono::duration<double, std::milli> dTimeSpan = std::chrono::duration<double,std::milli>(t2-t1);

    std::cout << "print start time span : " << dTimeSpan.count() << "ms\n";   
}

運行結果:

print 1000 stars
****************************....
print start time span : 0.091333ms

參考資料:
http://www.cplusplus.com/reference/chrono/
http://blog.csdn.net/u010487568/article/details/50512770


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM