<chrono> 溢出保证

<chrono> overflow guarantees

我有这段代码:

auto time_point_a = std::chrono::high_resolution_clock::now();
while (true) {
  auto time_point_b = std::chrono::high_resolution_clock::now();
  auto counter_ms = std::chrono::duration_cast<std::chromo::milliseconds(time_point_b - time_point_a);
  // more code
std::cont << counter_ms.count() << std::endl;
}

counter_ms.count() 是否保证始终 return 是一个有效值? count() 有可能抛出吗?如果 counter_ms 超过其基础整数类型的大小(我认为是 long long),会发生什么情况?我的程序将连续几天 运行,我需要知道会发生什么 if/when counter_ms 变得太大了。

Is counter_ms.count() guaranteed to always return a valid value?

counter_ms 保存一个带符号的毫秒整数计数。 .count() 成员函数被指定除了 return 这个带符号的整数值之外什么都不做。

Is there any chance that count() throws?

这个成员函数没有标记noexcept有两个原因:

  1. noexcept 在 std::lib 中很少使用。
  2. 一般来说,持续时间允许基于算术模拟器,它可能有一个抛出复制构造函数。

counter_ms的情况下,表示必须是有符号整数类型,当然不能抛出复制构造。

这不可能抛出。

What happens if counter_ms exceeds the size of its underlying integral type (I reckon it's long long)?

您可以使用此程序检查基础整数类型:

#include <chrono>
#include <iostream>
#include "type_name.h"

int
main()
{
    std::cout << type_name<std::chrono::milliseconds::rep>() << '\n';
}

其中 "type_name.h" 被描述为 here。对我来说,这个程序输出:

long long

标准规范规定此类型必须是至少 45 位的有符号整数类型。这使它的范围至少为 +/- 557 年。你可以用这个程序找到你实现milliseconds的实际范围:

#include <chrono>
#include <iostream>

int
main()
{
    using days = std::chrono::duration
        <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
    using years = std::chrono::duration
        <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;

    std::cout << std::chrono::duration_cast<years>
        (std::chrono::milliseconds::min()).count() << " years\n";
    std::cout << std::chrono::duration_cast<years>
        (std::chrono::milliseconds::max()).count() << " years\n";
}

对我来说输出:

-292277024 years
 292277024 years

巧合的是,我是实现我正在使用的 <chrono> 实现的人 (libc++)。实际范围比要求的最小范围大得多的原因是我在定位 45 位有符号整数类型时遇到了问题,不得不接受 64 位有符号整数类型。

超出此范围时,您将得到与有符号整数算术溢出(指定为未定义行为)完全相同的行为。