1. 程式人生 > >c++11 chrono全面解析(最高可達納秒級別的精度)

c++11 chrono全面解析(最高可達納秒級別的精度)

chrono是c++ 11中的時間庫,提供計時,時鐘等功能。

學習chrono,關鍵是理解裡面時間段(Durations)、時間點(Time points)的概念。

1.精度:

時鐘節拍(時間精度):

template <intmax_t N, intmax_t D = 1> class ratio;
其中N表示分子,D表示分母預設用秒錶示的時間單位

N對應於其成員num,D對應於其成員den

常用的單位:

ratio<60, 1>minute

ratio<1, 1>second

ratio<1, 1000>microsecond

...

ratio主要是是為後面將要講解的時間段,時間點等提供精度(單位)

[cpp] view plain copy print?
  1. #include<iostream>
  2. #include<chrono>
  3. usingnamespace std;  
  4. int main()  
  5. {  
  6.     cout << "millisecond : ";  
  7.     cout << std::chrono::milliseconds::period::num << "/" << std::chrono::milliseconds::period::den << 
    "s" <<endl;  
  8.     system("pause");  
  9. return 0;  
  10. }  
#include<iostream>
#include<chrono>
using namespace std;
int main()
{
	cout << "millisecond : ";
	cout << std::chrono::milliseconds::period::num << "/" << std::chrono::milliseconds::period::den << "s" <<endl;
	system("pause");
	return 0;
}

2.時間段:

template <class Rep, class Period = ratio<1> >
class duration;
std::chrono::duration 表示一段時間,比如兩個小時,12.88秒,半個時辰,一炷香的時間等等
Rep表示一種數值型別,用來表示Period的數量,比如int float double。 Period是ratio型別,用來表示上面所說的單位精度,比如second milisecond。 chrono中巨集定義了許多特例化了的duration: 就是常見的hours,miniutes,seconds,milliseconds等,使用std::chrono::milliseconds直接使用。 (1)建構函式很簡單 [cpp] view plain copy print?
  1. (1)duration() = default;    //預設構造
  2. (2)duration (const duration& dtn);        //(2)(3)拷貝構造
  3. (3)template<class Rep2, class Period2>  
  4.    constexpr duration (const duration<Rep2,Period2>& dtn);  
  5. (4)template<class Rep2>      //傳遞一個某型別(int等)的數值,構造一個時間段   
  6.    constexpr explicit duration (const Rep2& n);  
(1)duration() = default;    //預設構造
(2)duration (const duration& dtn);        //(2)(3)拷貝構造
(3)template<class Rep2, class Period2>
   constexpr duration (const duration<Rep2,Period2>& dtn);
(4)template<class Rep2>      //傳遞一個某型別(int等)的數值,構造一個時間段   
   constexpr explicit duration (const Rep2& n);

(2)成員函式count()返回單位時間的數量。

[cpp] view plain copy print?
  1. #include <iostream>
  2. #include <chrono>
  3. int main()  
  4. {  
  5.     std::chrono::milliseconds mscond(1000); // 1 second
  6.     std::cout << mscond.count() << " milliseconds.\n";  
  7.     std::cout << mscond.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;  
  8.     std::cout << " seconds.\n";  
  9.     system("pause");  
  10. return 0;  
  11. }  
#include <iostream>
#include <chrono>
int main()
{
	std::chrono::milliseconds mscond(1000); // 1 second
	std::cout << mscond.count() << " milliseconds.\n";

	std::cout << mscond.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;
	std::cout << " seconds.\n";
	system("pause");
	return 0;
}

(2)當不要求截斷值的情況下(時轉換成秒是沒問題,但是秒轉換成時就不行)時間段的轉換是隱式
的。顯示轉換可以由 std::chrono::duration_cast<> 來完成。
比如 std::chrono::milliseconds ms(54802);

std::chrono::seconds s=std::chrono::duration_cast<std::chrono::seconds>(ms);

這裡的結果就是截斷的,而不是進行了舍入,所以s最後的值將為54。

3.時間點:

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

std::chrono::time_point 表示一個具體時間,如上個世紀80年代、今天下午3點、火車出發時間等,只要它能用計算機時鐘表示。

第一個模板引數Clock用來指定所要使用的時鐘(標準庫中有三種時鐘,system_clock,steady_clock和high_resolution_clock。見4時鐘詳解),第二個模板函式引數用來表示時間的計量單位(特化的std::chrono::duration<> )

時間點都有一個時間戳,即時間原點。chrono庫中採用的是Unix的時間戳1970年1月1日 00:00。所以time_point也就是距離時間戳(epoch)的時間長度(duration)。

(1)建構函式:

(1)
time_point();           //預設建構函式,時間戳作為其值
(2)
template <class Duration2>
time_point (const time_point<clock,Duration2>& tp);  //拷貝建構函式
(3)
explicit time_point (const duration& dtn);           //使用duration構造,就是距離時間戳的時間長度
(2)時間點有個重要的函式:duration time_since_epoch()  (用於獲取當前時間點距離時間戳的時間長度)

即經常用來得到當前時間點到1970年1月1日00:00的時間距離、該函式返回的duration的精度和構造time_point的時鐘(Clock)有關(見4時鐘詳解)。

[cpp] view plain copy print?
  1. #include <iostream>
  2. #include <chrono>
  3. #include <ctime>
  4. usingnamespace std;  
  5. int main()  
  6. {  
  7. //距離時間戳2兩秒
  8.     chrono::time_point<chrono::system_clock, chrono::seconds> tp(chrono::seconds(2));  
  9.     cout << "to epoch : " <<tp.time_since_epoch().count() << "s" <<endl;  
  10. //轉化為ctime,列印輸出時間點
  11. time_t tt = chrono::system_clock::to_time_t(tp);  
  12. char a[50];  
  13.     ctime_s(a, sizeof(a), &tt);  
  14.     cout << a;  
  15.     system("pause");  
  16. return 0;  
  17. }  
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
int main()
{
	//距離時間戳2兩秒
	chrono::time_point<chrono::system_clock, chrono::seconds> tp(chrono::seconds(2));
	cout << "to epoch : " <<tp.time_since_epoch().count() << "s" <<endl;
	//轉化為ctime,列印輸出時間點
	time_t tt = chrono::system_clock::to_time_t(tp);
	char a[50];
	ctime_s(a, sizeof(a), &tt);
	cout << a;
	system("pause");
	return 0;
}

可以看出,時間戳就是使用的Unix的時間戳。

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()函式的返回值都依賴於時鐘的精度,測試時鐘的精度的一種方法就是:

[cpp] view plain copy print?
  1. <SPAN style="FONT-SIZE: 18px">#include <iostream>  
  2. #include <chrono>
  3. usingnamespace std;  
  4. int main()  
  5. {  
  6.     cout << "system clock          : ";  
  7.     cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << "s" << endl;  
  8.     cout << "steady clock          : ";  
  9.     cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << "s" << endl;  
  10.     cout << "high resolution clock : ";  
  11.     cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << "s" << endl;  
  12.     system("pause");  
  13. return 0;  
  14. }</SPAN>  
#include <iostream>
#include <chrono>
using namespace std;
int main()
{
	cout << "system clock          : ";
	cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << "s" << endl;
	cout << "steady clock          : ";
	cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << "s" << endl;
	cout << "high resolution clock : ";
	cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << "s" << endl;
	system("pause");
	return 0;
}

windows系統的測試結果是system_clock的精度是100納秒,而high_resolution的精度是1納秒,對於程式來說,一般毫秒級就夠了,所以說chrono提供的時鐘精度綽綽有餘。

(1)成員函式static time_point now() noexcept; 用於獲取系統的當前時間。

(2)由於各種time_point表示方式不同,chrono也提供了相應的轉換函式 time_point_cast。

template <class ToDuration, class Clock, class Duration>
  time_point<Clock,ToDuration> time_point_cast (const time_point<Clock,Duration>& tp);
傳一個要轉換為的精度的duration模板引數和一個要轉換的time_point引數(用法見下面綜合應用)

(3)其他成員函式:

to_time_t() time_point轉換成time_t秒

from_time_t() 從time_t轉換成time_point

綜合應用:

輸出當前時間,並且計算當前的時間距離1970年1月1日00:00的毫秒數

[cpp] view plain copy print?
  1. #include <iostream>
  2. #include <chrono>
  3. #include <ctime>
  4. usingnamespace std;  
  5. int main()  
  6. {  
  7. //定義毫秒級別的時鐘型別
  8. typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;  
  9. //獲取當前時間點,windows system_clock是100納秒級別的(不同系統不一樣,自己按照介紹的方法測試),所以要轉換
  10.     microClock_type tp = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());  
  11. //轉換為ctime.用於列印顯示時間
  12. time_t tt = chrono::system_clock::to_time_t(tp);  
  13. char _time[50];  
  14.     ctime_s(_time,sizeof(_time),&tt);  
  15.     cout << "now time is : " << _time;  
  16. //計算距離1970-1-1,00:00的時間長度,因為當前時間點定義的精度為毫秒,所以輸出的是毫秒
  17.     cout << "to 1970-1-1,00:00  " << tp.time_since_epoch().count() << "ms" << endl;  
  18.     system("pause");  
  19. return 0;  
  20. }  
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
int main()
{
	//定義毫秒級別的時鐘型別
	typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
	//獲取當前時間點,windows system_clock是100納秒級別的(不同系統不一樣,自己按照介紹的方法測試),所以要轉換
	microClock_type tp = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
	//轉換為ctime.用於列印顯示時間
	time_t tt = chrono::system_clock::to_time_t(tp);
	char _time[50];
	ctime_s(_time,sizeof(_time),&tt);
	cout << "now time is : " << _time;
	//計算距離1970-1-1,00:00的時間長度,因為當前時間點定義的精度為毫秒,所以輸出的是毫秒
	cout << "to 1970-1-1,00:00  " << tp.time_since_epoch().count() << "ms" << endl;
	system("pause");
	return 0;
}


通過兩張圖片對比,時間點上相差48-34=14秒、、下面的一長串數字,切掉3位(毫秒)、是28-14=14秒、、正確!說明這一串數字的最後三位就是毫秒數、、充分說明了達到了毫秒級別。

將上面的程式中millisconds換成microseconds或者更小的單位,便可達到微妙,甚至更高的精度。

相關推薦

c++11 chrono全面解析(最高級別精度)

chrono是c++ 11中的時間庫,提供計時,時鐘等功能。 學習chrono,關鍵是理解裡面時間段(Durations)、時間點(Time points)的概念。 1.精度: 時鐘節拍(時間精度): template <intmax_t N, intmax_t D = 1> class r

懶癌晚期學圖論的時候自己用C語言寫了個求性矩陣的演算法~

可達性矩陣演算法~ 直接上程式碼 #include <iostream> #include <cstring> using namespace std; #define n 5 void print(int a[n][n]); void print1(int a[n][n]); v

c++11智慧指標解析——揭開底層面紗,完整理解智慧指標

昨天跟同事小小的研究了下關於不同平臺下的位元組對齊問題,起因是遇到了一個坑,vs上沒有問題,在安卓上卻崩潰了。找了半天后發現是c++位元組補齊問題,期間包括使用#pragma pack(1)來限定位元組對齊方式等各種條件,也是把我們搞的七暈八素,總算是進一步瞭解了c++物件結構以及編譯器的操作(有機會的話

C語言測試 IP port 是否

#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h&g

[C#基礎知識系列]專題十:全面解析空型別

引言:   C# 2.0 中還引入了可空型別,可空型別也是值型別,只是可空型別是包括null的值型別的,下面就介紹下C#2.0中對可空型別的支援具體有哪些內容(最近一直都在思考如何來分享這篇文章的,因為剛開始覺得可空型別使用過程中比較簡單,覺得沒有講的必要,但是考慮到這

C++11 lambda 表達式解析

bar ... 以及 cal lam c++ iostream 沒有 red C++11 新增了很多特性,lambda 表達式是其中之一,如果你想了解的 C++11 完整特性,建議去這裏,這裏,這裏,還有這裏看看。本文作為 5 月的最後一篇博客,將介紹 C++11 的 la

C++11 std::chrono庫詳解

toolbar space max mil exp 值類型 cond 精度 ++i 所謂的詳解只不過是參考www.cplusplus.com的說明整理了一下,因為沒發現別人有詳細講解。   chrono是一個time library, 源於boost,現在已經是C++標準。

c++11 std::chrono

nbsp begin point duration argc ios iomanip poi count() #include <iostream> #include <iomanip> #include <ctime> #inclu

可見性和性,C#和C++

看C# premier有感, 以下是C#語言寫的類   class aBase{protect string s;} class aDerived:aBase{new private string s;}   new 關鍵字用以提示編譯器,s 是一個新的變數,故意隱藏基類裡面的

C++11chrono庫 實現高精度定時

一種“傳統”ctime計時方法: #include <ctime> using namespace std; clock_t start = clock(); // do something... clock_t end   = clock(); cout <<

Wannafly挑戰賽14 C-性(tarjan縮點+並查集)

思路來源 俊賢大佬 題解 tarjan縮點為無環圖, 每個強連通分量內的點排個序,取出標號最小的那個。 然後我們掃描等價的新圖。   若u和v在新圖裡面不是一個點,即來自不同的連通分量,//這句表達的思想很重要,網路流裡也有應用 且有邊u->v,

c++11計時:chrono

#include <chrono> std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); 某段程式碼 std:

C++11 function呼叫物件包裝器

// function.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。 // #include "pch.h" #include <iostream> #include <functional> using namespace std; vo

自從昨天我發現VS2012可以編譯出支援XP的程式碼之後,我決定在GacUI裡面全面使用C++11新功能

昨天研究發現,只要安裝了Update 1的Visual Studio 2012也可以編譯出支援XP的程式了。為了讓GacUI可以順利執行在XP上(雖然現在因為兩個api還不能),我一直試圖讓GacUI相容VS2010。VS2010對lambda的支援的bug很多,所以導致GacUI無法全面使用C+

C++11--時鐘和計時器<chrono>

/* 介紹<chrono> -- 一個精確中立的時間和日期庫 * 時鐘: * * std::chrono::system_clock: 依據系統的當前時間 (不穩定) * std::chrono::steady_clock: 以統一的速率執行(不能被調整)

C++獲得時間戳 C++11chrono

steady_clock::duration d = steady_clock::now().time_since_epoch(); minutes min = duration_cast<minutes>(d); seconds sec = duratio

[C# 基礎知識系列] 專題十五:全面解析擴充套件方法

引言:    C# 3中所有特性的提出都是更好地為Linq服務的, 充分理解這些基礎特性後。對於更深層次地去理解Linq的架構方面會更加簡單,從而就可以自己去實現一個簡單的ORM框架的,對於Linq的學習在下一個專題中將會簡單和大家介紹下,這個專題還是先來介紹服務於Li

C++11標準庫chrono庫使用

chrono是C++11新加入的方便時間日期操作的標準庫,它既是相應的標頭檔案名稱,也是std名稱空間下的一個子名稱空間,所有時間日期相關定義均在std::chrono名稱空間下。通過這個新的標準庫,可以非常方便進行時間日期相關操作。 chrono庫主要包含

C++11中的Lambda表示式構成之——捕獲值列表型別解析

摘抄之:捕獲值列表,是允許我們在Lambda表示式的函式體中直接使用這些值,捕獲值列表能捕獲的值是所有在此作用域可以訪問的值,包括這個作用域裡面的臨時變數,類的可訪問成員,全域性變數。捕獲值的方式分兩種,一種是按值捕獲,一種是按引用捕獲。顧名思義,按值捕獲是不改變原有變數的值

C++11:使用 auto/decltype/result_of使程式碼讀易維護

C++11 終於加入了自動型別推導。以前,我們不得不使用Boost的相關元件來實現,現在,我們可以使用“原生態”的自動型別推導了!C++引入自動的型別推導,並不是在向動態語言(強型別語言又稱靜態型別語言,是指需要進行變數/物件型別宣告的語言,一般情況下需要編譯執行。例如C/C