std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
这是一个很棒的地方auto
:
auto now = std::chrono::system_clock::now();
由于您想进行millisecond
精确的流量管理,因此最好在以下内容中进行隐蔽处理time_point
:
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
now_ms
是time_point
基于的system_clock
,但精度为milliseconds
而不是您system_clock
拥有的精度。
auto epoch = now_ms.time_since_epoch();
epoch
现在有类型std::chrono::milliseconds
。而下一条语句实际上变成了无操作(仅进行复制而没有进行转换):
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
这里:
long duration = value.count();
在您和我的代码中,都duration
包含milliseconds
以来的个数system_clock
。
这个:
std::chrono::duration<long> dur(duration);
创建一个以duration
表示的long
,精度为seconds
。有效地reinterpret_cast
将其milliseconds
保留value
为seconds
。这是一个逻辑错误。正确的代码如下所示:
std::chrono::milliseconds dur(duration);
这行:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
创建一个time_point
基于system_clock
的能力,该能力能够将精度保持为system_clock
的原始精度(通常小于毫秒)。但是,运行时值将正确反映保留了整数毫秒(假设我对的类型进行了更正dur
)。
即使进行了更正,该测试也会(几乎总是)失败,但是:
if (dt != now)
因为dt
拥有的整数milliseconds
,但是now
拥有比细的整数millisecond
(例如microseconds
或nanoseconds
)。因此,只有在极少的机会system_clock::now()
返回整数的milliseconds
情况下,测试才能通过。
但是您可以改为:
if (dt != now_ms)
现在,您将可靠地获得预期的结果。
放在一起:
int main ()
{
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::chrono::milliseconds dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
我个人觉得所有的std::chrono
细节都太冗长了,所以我将其编码为:
int main ()
{
using namespace std::chrono;
auto now = system_clock::now();
auto now_ms = time_point_cast<milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
milliseconds dur(duration);
time_point<system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
将可靠地输出:
Success.
最后,我建议消除临时变量,以将介于time_point
和整数类型之间的代码转换减至最少。这些转换很危险,因此编写的操作裸积分类型的代码越少越好:
int main ()
{
using namespace std::chrono;
auto now = time_point_cast<milliseconds>(system_clock::now());
using sys_milliseconds = decltype(now);
auto integral_duration = now.time_since_epoch().count();
sys_milliseconds dt{milliseconds{integral_duration}};
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
上面的主要危险并不解释integral_duration
为milliseconds
回到途中time_point
。减轻这种风险的一种可能方法是编写:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
这样可以将风险降低到仅确保您sys_milliseconds
在出门时使用和在返回时的两个位置使用。
和一个例子:你要转换,并从代表任何时间不可分割的假设system_clock
支持(微秒,10个微秒或纳秒)。然后,您不必担心指定上述毫秒数。该代码简化为:
int main ()
{
using namespace std::chrono;
auto now = system_clock::now();
auto integral_duration = now.time_since_epoch().count();
system_clock::time_point dt{system_clock::duration{integral_duration}};
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
这是可行的,但是如果您在一个平台上运行一半的转换(转换为整数),而在另一平台上运行另一半的转换(积分),则这system_clock::duration
将带来两次转换具有不同精度的风险。
std::chrono::duration<long,std::milli> dur
,即使这样,您也可能会遇到舍入错误(std::chrono::system_clock
分辨率可能比毫秒更高)。