std::chrono的time_point可以悄悄溢出吗?

问题描述 投票:0回答:1
#include <iostream>
#include <chrono>

int main()
{
  constexpr std::chrono::duration<float> kLastWarningMsgDuration{ 10 };

  // default time point (zero)
  std::chrono::steady_clock::time_point lastWarningMsgTime1;
  // minimum time point (some negative value)
  std::chrono::steady_clock::time_point lastWarningMsgTime2 = std::chrono::steady_clock::time_point::min();
  // current time point
  std::chrono::steady_clock::time_point lastWarningMsgTime3 = std::chrono::steady_clock::now();

  bool result1 = std::chrono::steady_clock::now() - lastWarningMsgTime1 >= kLastWarningMsgDuration;
  bool result2 = std::chrono::steady_clock::now() - lastWarningMsgTime2 >= kLastWarningMsgDuration;
  bool result3 = std::chrono::steady_clock::now() - lastWarningMsgTime3 >= kLastWarningMsgDuration;

  std::cout << result1 << std::endl;  // true, more than 10 seconds
  std::cout << result2 << std::endl;  // false ???
  std::cout << result3 << std::endl;  // false, less than 10 seconds
}

我没有深入研究这个问题,但我想问题是第二个结果溢出了可怜的 32 位

float
所能容纳的范围。我可以接受这个发现,但是有一件事一直困扰着我,那就是这个演示的大胆声明:

如果您进行了不涉及显式类型的合理更改 转换语法(并且它编译),您可以放心 没有引入错误。

嗯,这个信心现在对我来说已经相当动摇了。我是否误解了

time_point::min()
的作用,或者该说法并不完全正确?

c++ c++11 c++-chrono
1个回答
0
投票

这不是

float
溢出(那将是一个非常大的数字),
std::chrono::steady_clock::now() - lastWarningMsgTime2
正在取一些可能较小的正整数并减去最大大小的负整数。假设
std::chrono::steady_clock
使用
int64_t
你基本上在做:

int64_t lastWarningMsgTime2 = std::numeric_limits<int64_t>::min();
int64_t now = 12345;
int64_t diff = now - lastWarningMsgTime2;

这显然溢出了,因为

int64_t
已签名,这是未定义的行为(gcc 给出了一个很大的负数作为结果 https://godbolt.org/z/rPYM6oj75)。

大多数

std::chrono
实现在其持续时间中使用带符号的 64 位值,即使这些持续时间是纳秒,为您提供近 600 年的范围,因此在正常使用中,您引用的语句是正确的。显然仍然存在陷阱,减去
time_point::min()
是这些陷阱之一,但我看不出你通常想要这样做的原因。

© www.soinside.com 2019 - 2024. All rights reserved.