#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()
的作用,或者该说法并不完全正确?
这不是
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()
是这些陷阱之一,但我看不出你通常想要这样做的原因。