std::chrono разные результаты - фиксированный временной цикл
Может ли кто-нибудь помочь мне выяснить, в чем разница? Потому что первый код:
#include <iostream>
#include <chrono>
#include <ratio>
using namespace std::chrono;
const nanoseconds timePerFrame = duration_cast<nanoseconds>(duration<steady_clock::rep, std::ratio<1, 60>>(1));
nanoseconds accumulator(0);
nanoseconds counter(0);
steady_clock::time_point begin;
int i = 0;
int main()
{
while(true)
{
begin = steady_clock::now();
while(accumulator >= timePerFrame)
{
accumulator -= timePerFrame;
++i;
}
accumulator += steady_clock::now() - begin;
counter += steady_clock::now() - begin;
if(counter >= seconds(1))
{
std::cout << i << std::endl;
break;
}
}
}
Выходы: 30, и второй код:
#include <iostream>
#include <chrono>
#include <ratio>
using namespace std::chrono;
const nanoseconds timePerFrame = duration_cast<nanoseconds>(duration<steady_clock::rep, std::ratio<1, 60>>(1));
nanoseconds accumulator(0);
nanoseconds counter(0);
steady_clock::time_point begin;
steady_clock::time_point end;
int i = 0;
int main()
{
while(true)
{
begin = steady_clock::now();
while(accumulator >= timePerFrame)
{
accumulator -= timePerFrame;
++i;
}
end = steady_clock::now();
accumulator += end - begin;
counter += end - begin;
if(counter >= seconds(1))
{
std::cout << i << std::endl;
break;
}
}
}
Выходы: 60;
Единственное отличие заключается в использовании переменной end во втором примере. На мой взгляд, такой разницы не должно быть. Я имею в виду, не является ли stable_clock::now() точно таким же, как end = stable_clock::now()?
1 ответ
Разница в том, что здесь
accumulator += steady_clock::now() - begin;
counter += steady_clock::now() - begin;
два случая now()
вернуть 2 разных значения, таким образом counter
не будет в синхронизации с accumulator
и следующее условие if сработает на одну итерацию раньше по сравнению с
end = steady_clock::now();
accumulator += end - begin;
counter += end - begin;
потому что здесь оба, accumulator
а также counter
увеличиваются на ту же сумму.
Вы можете убедиться в этом, изменив порядок двух операторов на
counter += steady_clock::now() - begin;
accumulator += steady_clock::now() - begin;
это даст довольно непредсказуемый результат, в моем случае я получил 117.
Чтобы сделать код еще более читабельным, я бы написал так:
auto delta = end - begin;
accumulator += delta;
counter += delta;
Всегда хорошо избегать печатать одно и то же несколько раз. В этом случае действительно имеет значение, что они увеличиваются на одинаковую величину, так почему бы не сделать это явным образом в коде?!
TL; DR steady_clock::now()
такой же как end = steady_clock::now()
, но steady_clock::now()
не будет возвращать одно и то же значение, когда вы вызываете его дважды.