std::chrono::duration转换本质是编译期隐式类型转换,依赖ratio模板和rep类型兼容性;大单位转小单位静默允许,小单位转大单位会截断;duration_cast仅向下取整,非四舍五入。

std::chrono::duration 转换本质是隐式类型转换,不是“手动换算”
直接用 std::chrono::seconds 构造 std::chrono::milliseconds 不会出错,但别以为这是“计算”,其实是编译期单位换算。底层靠的是 ratio 模板——比如 milli 是 std::ratio,seconds 是 std::ratio。只要两个 duration 的 rep 类型兼容(如都是 int 或可隐式转),且目标单位能被源单位整除(或允许浮点),转换就静默发生。
- 安全转换:从大单位转小单位(如
seconds→milliseconds)默认允许,可能溢出但不报错 - 危险转换:从小单位转大单位(如
milliseconds→seconds)会截断小数部分,static_cast或duration_cast都不改变这一行为 - 浮点 rep 更稳妥:用
std::chrono::duration<double std::milli></double>可保留小数,避免整数截断
用 duration_cast 强制截断或舍入,不是“四舍五入”
duration_cast 只做向下取整(truncation toward zero),不是数学上的四舍五入。例如 599ms 转 seconds 得到 0s,-599ms 也得 0s。它只保证结果是目标单位的整数倍,丢弃余数。
- 想四舍五入?得自己加半单位再 cast:
duration_cast<seconds>(ms + milliseconds(500))</seconds> - 想向上取整?用
ceil配合浮点 duration:duration_cast<seconds>(ceil(double(ms.count()) / 1000.0) * seconds(1))</seconds> - 别对
auto变量直接 cast:如果原 duration 是nanoseconds,cast 到microseconds后仍保持rep类型,可能意外溢出
跨单位构造时,rep 类型不匹配会编译失败
写 milliseconds ms{3000}; seconds s{ms}; 能过,因为 int → int 兼容;但 milliseconds ms{3000LL}; seconds s{ms}; 就报错——long long 不能隐式转成 int。这不是单位问题,是 rep 类型不一致。
- 显式指定 rep 类型最稳:
using ms_t = duration<long long milli>; using s_t = duration<long long ratio>>;</long></long> - 用
count()+ 构造函数最灵活,但要自己处理换算系数:seconds s{ms.count() / 1000};(注意整除截断) - 避免混合使用 auto 和跨单位赋值:
auto d = milliseconds(1234); seconds s = d;—— 这里d的 rep 是int,若值超int范围,后续 cast 可能未定义
性能敏感场景下,避免不必要的 duration_cast
在循环里反复把 steady_clock::now() 的 time_point 转成 milliseconds 再 cast 成 seconds,其实做了两次单位换算。不如一次 cast 到最终需要的单位。
立即学习“C++免费学习笔记(深入)”;
- 高频调用时,优先用
duration_cast<target_unit>(tp.time_since_epoch())</target_unit>直接拿 epoch 偏移,比先转中间单位再 cast 快 - 调试打印别用
duration_cast套娃:直接用count()加单位说明更高效,比如ms.count() - 注意
system_clock::time_point和steady_clock::time_point的 epoch 不同,跨 clock 转换必须通过time_since_epoch()+duration_cast,不能直接赋值
实际写的时候,单位转换的麻烦往往不在语法,而在没想清楚要不要截断、该用什么 rep、以及 clock 类型是否可互转。这些细节不写进注释,过两周自己都看不懂为什么那里突然少了一秒。


















