前言
C++ 11 为我们提供了 chrono
库,这是一个好用且精准的计时库。
在 cstdlib
中也并不是没有计时函数,只不过 clock()
只能计算当前进程时间,time()
精度又十分低下。某些平台专用库文件如 windows.h
和 unistd.h
中的函数又不具备很好的跨平台性。因此,在 Boost
系列库中出现了一个优秀的计时库,就是我们今天要讲的 chrono
。
这个库如果要详解花费的篇幅会特别长,因此这里只介绍利用部分功能实现毫秒至纳秒级计时。
如果想要详细了解可以去看这篇文章。
chrono
中的所有函数等都定义在命名空间 std::chrono
中。因此依照竞赛类代码习惯应在头文件后加上以下代码。
using namespace std::chrono;
概念
首先我们需要知道几个概念。
duration
duration
是一个模板类,指的是一个时间段。它可以有不同的单位和计时方式,不过在此不必深究,我们只需要知道一些已经封装好的类就行了。
seconds // 以秒为单位
milliseconds // 以毫秒为单位
microseconds // 以微秒为单位
nanoseconds // 以纳秒为单位
duration_cast
duration_cast
是一个函数模板,因为 duration
可用的类型非常多,这个函数模板就用来进行不同类型间的转换。
time_point
time_point
也是一个模板类,指的是某个时间点。两个 time_point
相减可得到一个 duration
。
std::chrono::steady_clock
std::chrono::steady_clock
是一个结构体,封装了 chrono
中某些计时用的函数和类型方便调用。
应用
最典型的应用当然是给算法计时。
#include <cstdlib>
#include <chrono>
#include <iostream>
using namespace std;
using namespace chrono;
int main()
{
cout << "Begin counting..." << endl;
steady_clock::time_point BeginTime = steady_clock::now();
// do something
system("./t");
steady_clock::time_point EndTime = steady_clock::now();
// calculate the time
microseconds time_span = duration_cast<microseconds>(EndTime - BeginTime);
cout << (double) time_span.count() / 1000 << "ms.\n";
}
为了保证精准,我们可以使用微秒计时,但在最后转换为毫秒。
为了方便调用,也可以将这些函数再次封装,如封装成一个结构体。
struct Clock {
typedef steady_clock::time_point Clock_Type;
Clock_Type BeginTime, EndTime;
bool is_counting = false;
microseconds Clocks;
void begin()
{
if (!is_counting) {
BeginTime = steady_clock::now();
is_counting = true;
}
}
void end()
{
if (is_counting) {
EndTime = steady_clock::now();
is_counting = false;
Clocks = duration_cast<microseconds> (EndTime - BeginTime);
}
}
double clock()
{
return (double) Clocks.count() / 1000;
}
};
这样在调用的时候,只需要定义好一个变量,然后按顺序调用 begin()
、end()
,最后调用 clock()
就能得到精准的时间。
int main()
{
Clock count;
count.begin();
// do something
count.end();
cout << count.clock() << "ms.\n" << endl;
return 0;
}