如何从<chrono>中获取时长,以整型毫秒和浮点型秒表示?

124

我正在尝试使用chrono库进行计时器和时间段的操作。

我想要创建一个Duration frameStart;(从应用程序启动开始的时间)以及一个Duration frameDelta;(两帧之间的时间)

我需要能够以毫秒和浮点秒为单位获取frameDelta持续时间。

如何在新的C++11 <chrono>库中实现这一点?我一直在搜寻相关信息,但结果非常匮乏。这段代码具有很强的模板特性,还需要特殊的转换和处理,我无法正确使用这个库。


将比率秒(或毫秒)分配给持续时间,然后调用 count - K-ballo
自动 delta = duration_cast<seconds> (frameDelta).count(); 像这样?它返回的是 long long 而不是浮点数。 - EddieV223
3
如果你将一个高精度的时间段赋值给低精度的类型,那么这个赋值操作就是不合法的,因为这样会丢失精度。为了避免这种情况,你需要使用带有浮点数表示的时间段,或者使用duration_cast进行类型转换。 - Jonathan Wakely
@JonathanWakely:哦,那我一直在使用错误的方式!:( - K-ballo
5个回答

199

这是你正在寻找的吗?

#include <chrono>
#include <iostream>

int main()
{
    typedef std::chrono::high_resolution_clock Time;
    typedef std::chrono::milliseconds ms;
    typedef std::chrono::duration<float> fsec;
    auto t0 = Time::now();
    auto t1 = Time::now();
    fsec fs = t1 - t0;
    ms d = std::chrono::duration_cast<ms>(fs);
    std::cout << fs.count() << "s\n";
    std::cout << d.count() << "ms\n";
}

对我来说输出的是:

6.5e-08s
0ms

2
为什么不在 fsd 上使用 auto - TemplateRex
28
对于变量d,使用auto是可以的,因为duration_cast<ms>的结果是ms类型。但对于变量fs,使用auto就不合适了,因为t1-t0的结果是high_resolution_clock::duration类型,这个类型不一定与duration<float>相同。例如,在我的系统上它是duration<long long, nano>类型。因此,在那一行中,从基于整数的nanoseconds到基于浮点数的seconds存在隐式转换,只是因为指定了目标类型为fsec - Howard Hinnant
2
这是有用的信息。只是好奇:auto fs = std :: chrono :: duration_cast <fsec>(t1 - t0); 是否过于追求细节? - TemplateRex
1
@rhalbersma:那也可以很好地工作,并且做完全相同的事情。至于哪个更应该被优先考虑,就我而言,这完全是风格问题。 - Howard Hinnant
2
请注意,在某些实际场景中(例如MS编译器和库),'high_resolution_clock'将错过微秒级别的时间,因此此代码将输出零。 - jheriko
显示剩余8条评论

32

根据你的询问,我猜测你需要毫秒帧计时器的功能。我假设你正在寻找类似以下功能的东西。

double mticks()
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    return (double) tv.tv_usec / 1000 + tv.tv_sec * 1000;
}

但是使用的是 std::chrono

double mticks()
{
    typedef std::chrono::high_resolution_clock clock;
    typedef std::chrono::duration<float, std::milli> duration;

    static clock::time_point start = clock::now();
    duration elapsed = clock::now() - start;
    return elapsed.count();
}
希望这能有所帮助。

1
欢迎来到 Stack Overflow。如果您能提供代码的附加细节,那就太好了。这将有助于其他人了解您试图完成的任务以及您的解决方案的工作原理。谢谢! - Luís Cruz
4
FYI -- 这是我审阅过的数十个例子中最清晰、最有用的一个。感谢你让永恒令人困惑的时间函数易于理解。 - SMGreenfield
为什么要将start声明为静态的?这样可能会导致编译器在其周围放置保护。你是不是想使用const代替? - ZachB
太棒了!唯一一个不使用乘除或duration_cast的答案!!要获取以毫秒为单位的持续时间:std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0}; - x4444

18

我不知道"毫秒和浮点秒"是什么意思,但这应该可以给你一个想法:

#include <chrono>
#include <thread>
#include <iostream>

int main()
{
  auto then = std::chrono::system_clock::now();
  std::this_thread::sleep_for(std::chrono::seconds(1));
  auto now = std::chrono::system_clock::now();
  auto dur = now - then;
  typedef std::chrono::duration<float> float_seconds;
  auto secs = std::chrono::duration_cast<float_seconds>(dur);
  std::cout << secs.count() << '\n';
}

我猜他想要实际的 count 作为 float 类型? - K-ballo
1
这就是最后打印出来的内容。但我不知道他想要毫秒作为整数,还是毫秒过去了一秒,或者其他什么。 - Jonathan Wakely
我希望能够从chrono::duration中获取以整数毫秒或浮点秒(秒的小数部分)表示的持续时间。 - EddieV223
Howard的回答正是如此。 - Jonathan Wakely

9

使用显式类型初始化惯用语AAA样式中:

#include <chrono>
#include <iostream>

int main(){
  auto start = std::chrono::high_resolution_clock::now();
  // Code to time here...
  auto end = std::chrono::high_resolution_clock::now();

  auto dur = end - start;
  auto i_millis = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
  auto f_secs = std::chrono::duration_cast<std::chrono::duration<float>>(dur);
  std::cout << i_millis.count() << '\n';
  std::cout << f_secs.count() << '\n';
}

对于像获取毫秒持续时间这样简单的情况,你不应该使用duration_cast。要获取以毫秒为单位的持续时间:std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0}; - x4444
@x4444 谁说“你不应该使用duration_cast?”这似乎是一个风格问题。你可以选择以几乎总是自动的方式编写代码,并明确地进行类型转换,或者不使用auto并隐式地进行类型转换。你有权喜欢其中一种风格胜过另一种,但移除duration_cast并不会使代码运行更快。 - Chris Drew

0
float GetTimeFloat() {
    return std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() / 1000;
}

2
嗨Reuniko!感谢您贡献答案,但请在以后尽量避免“仅代码”的回答,并在您的代码片段周围添加一些解释,参见如何回答。谢谢! - joshmeranda
每次你在使用乘法或除法与chrono结合时,都是错误的!正确的写法是std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0}; - x4444

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接