C++11 標(biāo)準(zhǔn)庫源代碼剖析:連載之五

std::chrono

說起來有點(diǎn)令人難以置信,直到C++ 11之前,標(biāo)準(zhǔn)庫中唯一可以處理時間的就是<ctime>提供的有限的幾個函數(shù),而即使這有限的幾個函數(shù)還是C函數(shù)慌洪,這使得在C++中處理時間成為一件頭疼的事情。不過現(xiàn)在情況有了很大改觀凑保,因?yàn)橛辛?code>std::chrono冈爹。

chrono簡介

chrono是一個基于模板的,面向?qū)ο蟮挠涫剩O(shè)計(jì)優(yōu)雅且功能強(qiáng)大的time library犯助。chrono內(nèi)部定義了三種和時間相關(guān)的類型:

  • duration:一個duration就代表了一個時間段,比如2分鐘维咸,4小時等等剂买。

  • clock: clock的作用就相當(dāng)于我們?nèi)粘J褂玫氖直恚猴@示時間。chrono內(nèi)部定義了三種clocksystem clock癌蓖、steady clockhigh-resolution-clock瞬哼。

  • time pointtime point表示某個特定的時間點(diǎn)。

std::duration

前面說過租副,duration代表了一段時間坐慰,比如2分鐘,4小時等用僧。注意我不僅指出了數(shù)量(“2”结胀、“4”)赞咙,還指出了單位(“分鐘”,“小時”)糟港,也就是說一個duration的定義應(yīng)該包括兩個部分:數(shù)量和單位攀操。我們來看chrono是怎樣做到這一點(diǎn)的。

// file: chrono

namespace chrono {

    template<class _Rep, class _Period = ratio<1> >
    class duration {
    public:
        typedef _Rep     rep;
        typedef _Period  period;
    private:
        rep __rep_;
    
    // ...
    };
}

duration的聲明包含兩個模板參數(shù)秸抚,第一個模板參數(shù)是C++的原生數(shù)值類型速和,如long, long long等,代表了duration的數(shù)值部分剥汤。第二個模板參數(shù)_Period又是一個模板類std::ratio颠放,它的定義如下:

// file: ratio

namespace chrono {

    // ratio以模板的方式定義了有理數(shù),比如ratio<1,60>就表示有理數(shù) ‘1/60’
    // _Num代表 'numerator'(分子)
    // _Den代表 'denominator'(分母)
    template<intmax_t _Num, intmax_t _Den = 1>
    class ration {
    
        // 求__Num的絕對值
        static constexpr const intmax_t __na = __static_abs<_Num>::value;
    
        // 求_Den的絕對值
        static constexpr const intmax_t __da = __static_abs<_Den>::value;
    
        // __static_sign的作用是求符號運(yùn)算
        static constexpr const intmax_t __s = __static_sign<_Num>::value * __static_sign<_Den>::value;
    
        // 求分子吭敢、分母的最大公約數(shù)
        static constexpr const intmax_t __gcd = __static_gcd<__na, __da>::value;
    
    public:
    
        // num是化簡后的_Num
        static constexpr const intmax_t num = __s * __na / __gcd;
    
        // den是化簡后的_Den
        static constexpr const intmax_t den = __da / __gcd;
    };
}

ratio用兩個整數(shù)型模板參數(shù)來表示一個有理數(shù)的分子和分母部分碰凶,比如ratio<1, 1000>就表示有理數(shù)0.001。理解了這一點(diǎn)省有,我們再來看duration的定義:

template<class _Rep, class _Period = ratio<1> > class duration 

ratio在這里的確切含義為:以秒為單位的放大倍率痒留,比如ratio<60, 1>表示一個1秒的60倍,也就是1分鐘蠢沿,而ratio<1, 1000>表示1秒的千分之一倍,也就是1毫秒匾效。所以duration<long, ratio<60, 1>>就定義了一個類型為longduration舷蟀,而這個duration的單位為“分鐘”。很巧妙的定義面哼,是不是野宜?

為了方便我們使用,對常用的時間單位魔策,標(biāo)準(zhǔn)庫都已經(jīng)替我們定義好了:

namespace chrono {

    // 1nano = 1/1,000,000,000 秒
    typedef ratio<1LL, 1000000000LL> nano;

    // 1micro = 1/1,000,000秒
    typedef ratio<1LL, 1000000LL> micro;

    // 1milli = 1/1,000秒
    typedef ratio<1LL, 1000LL> milli;

    // 1centi = 1/100秒
    typedef ratio<1LL, 100LL> centi;

    // 1kilo = 1,000秒
    typedef ratio<1000LL, 1LL> kilo;

    // 1mega = 1,000,000秒
    typedef ratio<1000000LL, 1LL> mega;
    
    // ...
    
    typedef duration<long long,         nano> nanoseconds;
    typedef duration<long long,        micro> microseconds;
    typedef duration<long long,        milli> milliseconds;
    typedef duration<long long              > seconds;
    typedef duration<     long, ratio<  60> > minutes;
    typedef duration<     long, ratio<3600> > hours;
    
    // ...
}

duration的用法

標(biāo)準(zhǔn)委員會重寫了標(biāo)準(zhǔn)庫中全部和時間有關(guān)的函數(shù)匈子,使之可以和duration協(xié)同工作,這使得duration的使用非常簡單直觀闯袒,舉個例子:

#include <iostream>
#include <chrono>
#include <thread>
 
int main()
{
    // 定義一個"chrono::seconds"
    std::chrono::seconds two_seconds{2}; 
    std::cout << "Start waiting..." << std::endl;
    auto start = std::chrono::high_resolution_clock::now();
    
    // sleep_for函數(shù)現(xiàn)在接受一個`duration`類型的參數(shù)
    std::this_thread::sleep_for(two_seconds);
    
    auto end = std::chrono::high_resolution_clock::now();
    
    // duration支持算術(shù)運(yùn)算
    std::chrono::duration<double, std::milli> elapsed = end-start;
    std::cout << "Waited " << elapsed.count() << " ms\n";
}

// output
Start waiting...
Waited 2002.58 ms

為什么你應(yīng)該使用duration

  1. duration是輕量級的虎敦,在前面的源代碼中我們已經(jīng)看到了,duration內(nèi)部僅有一個數(shù)值類型的變量政敢,很是輕量級其徙。至于ratio,因?yàn)槠涑蓡T變量都是靜態(tài)的喷户,所以你不用擔(dān)心系統(tǒng)內(nèi)會有很多的ratio存在唾那。

  2. duration是類型安全的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末褪尝,一起剝皮案震驚了整個濱河市闹获,隨后出現(xiàn)的幾起案子期犬,更是在濱河造成了極大的恐慌,老刑警劉巖避诽,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龟虎,死亡現(xiàn)場離奇詭異,居然都是意外死亡茎用,警方通過查閱死者的電腦和手機(jī)遣总,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轨功,“玉大人旭斥,你說我怎么就攤上這事」沤В” “怎么了垂券?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長羡滑。 經(jīng)常有香客問我菇爪,道長,這世上最難降的妖魔是什么柒昏? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任凳宙,我火速辦了婚禮,結(jié)果婚禮上职祷,老公的妹妹穿的比我還像新娘氏涩。我一直安慰自己,他們只是感情好有梆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布是尖。 她就那樣靜靜地躺著,像睡著了一般泥耀。 火紅的嫁衣襯著肌膚如雪饺汹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天痰催,我揣著相機(jī)與錄音兜辞,去河邊找鬼。 笑死陨囊,一個胖子當(dāng)著我的面吹牛弦疮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜘醋,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胁塞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啸罢,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤编检,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扰才,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體允懂,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年衩匣,在試婚紗的時候發(fā)現(xiàn)自己被綠了蕾总。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡琅捏,死狀恐怖生百,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柄延,我是刑警寧澤蚀浆,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站搜吧,受9級特大地震影響市俊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滤奈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一摆昧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜒程,春花似錦据忘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曼追。三九已至窍仰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間礼殊,已是汗流浹背驹吮。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晶伦,地道東北人碟狞。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像婚陪,于是被迫代替她去往敵國和親族沃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容