65.9K
CodeProject 正在变化。 阅读更多。
Home

用于更精确测量时间间隔的 C++ 类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.66/5 (25投票s)

2001年10月12日

Ms-PL

2分钟阅读

viewsIcon

171280

downloadIcon

2736

能够在 Windows 操作系统下以微秒为单位测量时间间隔的 C++ 类。

引言

这个计时器类能够以微秒为单位测量 Windows 操作系统下的时间间隔。它使用不太为人所知的 Windows API 函数 QueryPerformanceFrequency()QueryPerformanceCounter() 来获取高精度性能计数器的频率和计数。对于没有这种高精度性能计数器的系统,将使用更常用的 API 函数 GetTickCounts(),但这会降低计时器的精度。无论如何,计时器的可靠性取决于系统的硬件性能,也就是说,对于处理器频率更高的系统,精度会提高。该类还演示了一些关于在 VC++ 中使用 __int64 整数的有用技巧。

实现

在这里,我只展示了 CPreciseTimer 类的公共用户界面,实现细节在演示项目的源代码文件中。

class CPreciseTimer
{
public:
    CPreciseTimer();
    bool SupportsHighResCounter();
    void StartTimer();
    void StopTimer();
    __int64 GetTime();
};
  • 构造函数 CPreciseTimer() 在首次实例化该类时,还会确定是否可以使用高精度性能计数器,如果可以使用,则初始化频率成员变量。后续构造不会重复这个计算块。

  • 函数 SupportsHighResCounter() 仅当高精度性能计数器可用时才返回 true。它为用户提供了关于计时器精度的提示。

  • 函数 StartTimer(),顾名思义,是启动计时器。

  • 函数 StopTimer() 停止计时器,同时保留自计时器启动以来经过的时间。

  • 函数 GetTime() 如果计时器处于运行状态,则返回自计时器启动以来经过的时间间隔。如果计时器处于停止状态,则返回上次停止调用和上次启动调用之间的时间差。返回值以微秒为单位,但如果高精度性能计数器不可用,则不能信任该值,在这种情况下,精度实际上不可能高于毫秒级。

如何使用

以下代码片段显示了一个简单的使用示例

CPreciseTimer oPreciseTimer;
cout << "Starting!" << endl;
oPreciseTimer.StartTimer();
::Sleep(5000);
cout << "Ending!" << endl;
oPreciseTimer.StopTimer();
__int64 i64Diff = oPreciseTimer.GetTime();
cout << "Diff=" << Int64ToString(i64Diff) << endl;
return 0;

我使用自己的函数 Int64ToString() 来显示 __int64 数字。我也免费提供此函数供您使用

string Int64ToString(__int64 const& ri64, int iRadix=10)
{
    bool bNeg = (ri64 < 0);
    __int64 i64 = ri64;
    string ostrRes;
    bool bSpecial = false;
    if(true == bNeg)
    {
        i64 = -i64;
        if(i64 < 0)
        // Special case number -9223372036854775808 or 
        // 0x8000000000000000
        bSpecial = true;
        ostrRes.append(1, '-');
    }
    int iR;
    do
    {
        iR = i64 % iRadix;
        if(true == bSpecial)
            iR = -iR;
        if(iR < 10)
            ostrRes.append(1, '0' + iR);
        else
            ostrRes.append(1, 'A' + iR - 10);
        i64 /= iRadix;
    }
    while(i64 != 0);
    //Reverse the string
    string::iterator it = ostrRes.begin();
    if(bNeg)
        it++;
    reverse(it, ostrRes.end());
    return ostrRes;
}

它能够以任何基数(默认基数为 10)显示 __int64 值。__int64 值也可以使用 printf() 函数显示,如下代码片段所示

__int64 i64 = 0x7fffffffffffffff;
printf("Decimal Value = %I64d\n", i64);
printf("Hexa Value = %I64x\n", i64);

您也可以在 MFC 应用程序中使用 CStringFormat() 函数

CString str;
str.Format("%I64d", 4294967307);

或者一个 stdlib 函数 _i64toa(),它类似于 itoa()

__int64 i64 = 4294967307;
char szBuff[20];
_i64toa(i64, szBuff, 10);

结论

本文附带的项目包含了所介绍的 CPreciseTimer 类和测试代码的源代码。我对有关此实现的任何意见和新想法都感兴趣。

© . All rights reserved.