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)部定義了三種clock:system clock
癌蓖、steady clock
和high-resolution-clock
瞬哼。time point:time 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>>
就定義了一個類型為long
的duration
舷蟀,而這個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
duration
是輕量級的虎敦,在前面的源代碼中我們已經(jīng)看到了,duration
內(nèi)部僅有一個數(shù)值類型的變量政敢,很是輕量級其徙。至于ratio
,因?yàn)槠涑蓡T變量都是靜態(tài)的喷户,所以你不用擔(dān)心系統(tǒng)內(nèi)會有很多的ratio
存在唾那。duration
是類型安全的。