基于<chrono> </chrono>改进计时器类

时间:2012-11-17 13:55:31

标签: c++ c++11 chrono

我有以下Timer类来简化从一个纪元以来经过的时间:

#include <chrono>

class Timer {
  public:
    void start(void);
    template <typename duration_type>
    const duration_type time_elapsed(void);
  private:
    std::chrono::high_resolution_clock::time_point epoch;
};

void Timer::start(void) {
  epoch = std::chrono::high_resolution_clock::now();
}

template <typename duration_type>
const duration_type Timer::time_elapsed(void) {
  return std::chrono::duration_cast<duration_type>(std::chrono::high_resolution_clock::now() - epoch);
}

int main(void) {
  Timer timer;

  timer.start();

  // pointless loop to cause a delay
  for (int x = 1; x < 1000000; ++x) {
    x * x * x;
  }

  std::chrono::nanoseconds elapsed = timer.time_elapsed<std::chrono::nanoseconds>();
  std::cout << elapsed.count() << std::endl;

  return 0;
}

我有一种感觉,我通过使Timer :: time_elapsed()成为模板函数来使我的课程过于复杂,并且理想情况下希望将其用法简化为以下内容:

  std::chrono::nanoseconds elapsed = timer.time_elapsed();
  std::cout << elapsed.count() << std::endl;

2 个答案:

答案 0 :(得分:4)

我修复了代码中的一些内容并添加了std::chrono的正确用法。更改列表包括:

  1. 我从函数调用中删除了所有(void)个参数,因为它不是这样的C ++方式: - )
  2. 我还从return 0;中删除了main(),这是C ++中不需要的,因为编译器会为你提供它。
  3. 我输入了一个时钟,因为现在很难在当前的实现中找到一个高质量的时钟。请参阅我的回答here。基本上你现在可能想要使用你的自定义时钟,并且感谢typedef重构可能会在将来更容易。
  4. 我将你的等待循环更改为C ++ 11睡眠界面(如果你愿意,你可以在那里随机化一些持续时间 - 也可以使用C ++ 11 :-))。在这种情况下不需要进行更改,但很好地说明了std::chrono在线程库中的使用方式。
  5. 我将您的方法实现放在一个类中,以便为编译器提供内联它们的机会。或者,您可以在类之外的实现中使用inline关键字明确表达。
  6. 我制作了time_elapsed()方法const
  7. 我从const方法的返回值中删除了不必要的time_elapsed(),并将其添加到另一方面使用该方法,因为在那个确切的位置const就足够了。
  8. 最后但并非最不重要的是,我修改了time_elapsed()方法,以便在return中返回时钟的原始分辨率。这是更好的解决方案,因为您从未在此处丢失数据。在向特定单位(即我们)提供数据时,您可能希望将其丢失。你必须在那里使用duration_cast告诉编译器你同意丢失一些数据,我们的分辨率就足够了。
  9. 我希望以下代码及以上更改对您有意义。

    #include <chrono>
    #include <thread>
    #include <iostream>
    
    using namespace std::chrono;
    
    class Timer {
    public:
      typedef high_resolution_clock Clock;
      void start()
      { epoch = Clock::now(); }
      Clock::duration time_elapsed() const
      { return Clock::now() - epoch; }
    private:
      Clock::time_point epoch;
    };
    
    int main() {
      Timer timer;
      timer.start();
    
      // sleep some time
      std::this_thread::sleep_for(microseconds(40));
    
      const auto elapsed = timer.time_elapsed();
      std::cout << duration_cast<microseconds>(elapsed).count() << "us" << std::endl;
    }
    
    顺便说一句,我不想​​玩类接口(我已经做了太多的改动)。如果您不受该界面的约束,我建议遵循@sehe建议的那个。但是不要使用double作为返回值; - )

答案 1 :(得分:1)

返回一个存储now-epoch()的辅助类,并在经过时间后对运算符T进行高精度转换。或者,有一个time_elapsed_in_units<T>方法,看起来你的时间已经过去,然后经过一段时间,返回一个在运算符T上调用单位的结构。

辅助类操作符T的过度加载让您可以隐式地检测被调用的类型。