author: hjjdebug
date: 2025年 05月 20日 星期二 14:36:17 CST
descrip: std::chrono類的簡單使用實例及分析
文章目錄
- 1.實例代碼:
- 2. 代碼分析:
- 2.1 auto t1 = std::chrono::high_resolution_clock::now();
- 2.1.1 什么是 system_clock
- 2.1.2 什么是 chrono::time_point?
- 2.1.3 什么是duration?
- 2.1.3.1 duration 的一個實例
- 2.1.4 這么多的內涵,到底怎樣理解time_point呢?
- 2.1.5 time_point t1 在gdb中的表示
- 2.2 auto delta_t = t2 - t1;
- 2.3 auto dur_obj = std::chrono::duration<double, std::milli>(delta_t);
- 2.3.1 duration 對象能夠知道數值代表的是毫秒,納秒或者其它單位嗎?
1.實例代碼:
$ cat main.cpp
#include <iostream>
#include <unistd.h> //for sleep
#include <chrono>
using namespace std;int main() {//now()是類的靜態函數, auto t1 = std::chrono::high_resolution_clock::now(); //t1 是time_point 對象, time_point 對象是什么?// 被測代碼sleep(1);auto t2 = std::chrono::high_resolution_clock::now(); // 返回的是時間點對象auto delta_t = t2 - t1; //2個time_point 對象相減,肯定被重構了. 返回的是 duration 對象, duration 對象是什么?auto dur_obj = std::chrono::duration<double, std::milli>(delta_t); //構造函數,參數是duration對象,返回ms為單位的duration對象std::cout << "耗時:" << dur_obj.count() << "ms" <<endl; //訪問其數值,通過count(), 我們構建的是ms為單位的對象,所以單位就是msdur_obj = std::chrono::duration<double, std::milli>(500); //另一個構造函數,給500就打印500,單位還是ms,由std::milli類型決定的.std::cout << "測試打印:" << dur_obj.count() << "ms" <<endl;return 0;
}
執行結果
$ ./temp
耗時:1000.14ms
測試打印:500ms
代碼很短,可是內涵很豐富. 是c++模板類的入門之路.
下面幾乎是逐句分析了.
2. 代碼分析:
2.1 auto t1 = std::chrono::high_resolution_clock::now();
std: namespace
chrono: namespace
大命名空間下的小命名空間,此時的命名空間為std::chrono
using high_resolution_clock = system_clock;
using 與typedef 類似, 也與#define 有可比性. 就是說high_resolution_clock 這個類型
是 system_clock 類型的小名, 它們是一個類型. 由此引出 system_clock 類型
2.1.1 什么是 system_clock
struct system_clock{ //定義了一堆類型別名, 告訴編譯器說, 別慌, 有一堆類型記住它們的小名.typedef chrono::nanoseconds duration; //使用ns做durationtypedef duration::rep rep;typedef duration::period period;typedef chrono::time_point<system_clock, duration> time_point;//靜態變量是屬于類的變量, 是全局的.static constexpr bool is_steady = false;//靜態函數是屬于類的函數. 恰似普通的函數, 執行不使用this指針,有3個//成員函數 now() to_time_t(time_point &t), from_time_t(std::time_t t)static time_point now() noexcept;static std::time_tto_time_t(const time_point& __t) noexcept{return std::time_t(duration_cast<chrono::seconds>(__t.time_since_epoch()).count());}static time_pointfrom_time_t(std::time_t __t) noexcept{typedef chrono::time_point<system_clock, seconds> __from;return time_point_cast<system_clock::duration>(__from(chrono::seconds(__t)));}};
now 是system_clock 類的靜態成員函數, 返回一個time_point 類型對象
2.1.2 什么是 chrono::time_point?
看一下它的聲明,
template<class Clock, class Duration = typename Clock::duration> class time_point;
它是一個類模板. 有兩個類型參數.
時鐘類型決定了時間的來源, 有system_clock, steady_clock,high_resolution_clock(是system_clock的代名詞)
system_clock, 前面已經有交代.
劇透一下 system_clock 的紀元為 1970-01-01 00:00:00 UTC), unix時間戳起點
system_clock是time_point類模板的第一個參數.
time_point類模板的第二個參數類型duration 是什么?
2.1.3 什么是duration?
duration 是一個類型,這里先給duration的一個實例.
2.1.3.1 duration 的一個實例
(gdb) ptype dur_obj
type = struct std::chrono::duration<double, std::ratio<1, 1000> > [with _Rep = double, _Period = std::ratio<1, 1000>] {private:_Rep __r;public:duration(void);duration(const std::chrono::duration<_Rep, _Period> &);~duration();std::chrono::duration<_Rep, _Period> & operator=(const std::chrono::duration<_Rep, _Period> &);_Rep count(void) const;std::chrono::duration<_Rep, _Period> operator+(void) const;std::chrono::duration<_Rep, _Period> operator-(void) const;std::chrono::duration<_Rep, _Period> & operator++(void);std::chrono::duration<_Rep, _Period> operator++(int);std::chrono::duration<_Rep, _Period> & operator--(void);std::chrono::duration<_Rep, _Period> operator--(int);std::chrono::duration<_Rep, _Period> & operator+=(const std::chrono::duration<_Rep, _Period> &);std::chrono::duration<_Rep, _Period> & operator-=(const std::chrono::duration<_Rep, _Period> &);std::chrono::duration<_Rep, _Period> & operator*=(const _Rep &);std::chrono::duration<_Rep, _Period> & operator/=(const _Rep &);static std::chrono::duration<_Rep, _Period> zero(void);static std::chrono::duration<_Rep, _Period> min(void);static std::chrono::duration<_Rep, _Period> max(void);void duration<int>(const int &);void duration<double>(const _Rep &);void duration<long, std::ratio<1, 1000000000> >(const std::chrono::duration<long, std::ratio<1, 1000000000> > &);typedef _Rep rep;
}
它有一個私有成員變量 _Rep __r, __Rep 是represent的簡寫, 是類模板的第一個類型參數.可能是double或long
類模板還有第2個類型參數, 此處是 std::ratio<1,1000> 類型, 這個類型起碼有2個類屬性可以使用
std::ratio<1,1000>::num=1
std::ratio<1,1000>::den=1000
至于其它構造,析構,重載運算符就不具體分析了.
2.1.4 這么多的內涵,到底怎樣理解time_point呢?
時間點對象timepoint是時間點類模板用system_clock 和 nanoseconds 為類型參數實例化后的一個對象.它有一個duration類型的變量記錄其屬性
其值說明是從 1970-01-01 00:00:00 開始的 納秒數, 用long int 表示的數
2.1.5 time_point t1 在gdb中的表示
time_point 包含一個duration 對象 __d, duration對象包含一個實現類型(long或double)變量 __r
(gdb) p t1
$1 = {
__d = {
__r = 1747640811095678930 //1970-01-01 00:00:00開始的時間, 單位僅從對象本身是看不出來的.
}
}
//從類模板類型參數上知道它是ns, 但模板類型參數僅僅是編譯期屬性, 編譯期知道它是ns, 但運行期就不知道了.
(gdb) ptype t1 ,
type = struct std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long, std::ratio<1, 1000000000> > > [with _Clock = std::chrono::_V2::system_clock, _Dur = std::chrono::duration<long, std::ratio<1, 1000000000> >] {private:_Dur __d; //私有成員變量, duration 類型public:time_point(void);time_point(const _Dur &);_Dur time_since_epoch(void) const;std::chrono::time_point<_Clock, _Dur> & operator+=(const _Dur &);std::chrono::time_point<_Clock, _Dur> & operator-=(const _Dur &);static std::chrono::time_point<_Clock, _Dur> min(void);static std::chrono::time_point<_Clock, _Dur> max(void);typedef _Dur duration;
}(gdb) p t2
$2 = {__d = {__r = 1747640813823889979 //unix 時間點到現在的時間間隔}
}
2.2 auto delta_t = t2 - t1;
//兩個時間點之差是duration 變量
//2個time_point 對象相減,運算被重構了. 返回的是 duration 對象
(gdb) p delta_t //一種duration 對象
$3 = {
__r = 2728211049
}
(gdb) p dur_obj //另一種duration 對象
$4 = {
__r = 2728.211049
}
2.3 auto dur_obj = std::chrono::duration<double, std::milli>(delta_t);
代碼分析:
std::chrono namespace
duration<double, std::milli>: 是一個實例化模板類
std::chrono::duration<double,std::milli>(delta_t);
類名稱后面跟上一個參數(這里是duration為參數)就是構建對象的過程(copy構造)
auto dur_obj = std::chrono::duration<double, std::milli>(delta_t); (賦值構造)
把一個無名對象賦值給一個有名對象 dur_obj
duration 對象是什么?數值代表了什么意思?
請參考2.1.4 說明duration 對象是什么類型
2.3.1 duration 對象能夠知道數值代表的是毫秒,納秒或者其它單位嗎?
答: 對于一個duration 對象
$4 = {
__r = 2728.211049
}
duration 本身并不知道數值代表的是ms,ns或其它單位.
但是duration類卻能夠根據構造函數傳來的類型及模板參使用的類型對傳來的數值進行轉換.
這是靜態編譯的能力.
現在已經計算出了這個值并付給了對象的成員. 但這個對象已經不知道自己是什么單位了,
因為對象本身沒有保留單位信息. 即單位信息做為模板類型參數不是運行期特性只是編譯期特性.
那我們怎么知道數值的單位是什么呢?
這是你自己的問題, 你自己根據數值的轉變過程確定它應該是什么單位.