std::chrono::duration不能直接用秒的整数倍定义新单位,因其模板参数rep和period必须是编译期确定的整型和std::ratio有理数;自定义单位如1.5秒需写为std::ratio,浮点写法非法;转换依赖duration_cast,存在截断或溢出风险。

为什么 std::chrono::duration 不能直接用秒的整数倍定义新单位?
因为 std::chrono::duration 的模板参数是 Rep(底层表示类型)和 Period(编译期有理数,如 std::ratio),不是运行时数值。所谓“自定义时间单位”,本质是定义一个新的 Period 类型,而非给已有 duration 赋个新名字。
如何正确定义毫秒、微秒以外的单位(比如 1.5 秒)?
必须用 std::ratio 表达精确的有理数比例。例如 1.5 秒 = 3/2 秒 → std::ratio;0.1 秒 = 1/10 秒 → std::ratio。不能用浮点或小数写法,否则编译失败。
using one_and_half_seconds = std::chrono::duration<long std::ratio>>;</long>using decisecond = std::chrono::duration<int std::ratio>>;</int>- 错误写法:
std::chrono::duration<double std::ratio>></double>(std::ratio只接受整型模板参数)
自定义单位和标准单位之间转换是否安全?
只要底层 Rep 足够宽,且转换不溢出,std::chrono::duration_cast 是隐式或显式安全的。但要注意截断行为:从细粒度转粗粒度(如纳秒→自定义 3 秒单位)会丢精度;反过来可能溢出。
auto d = std::chrono::seconds(5);auto custom = std::chrono::duration_cast<one_and_half_seconds>(d); // 结果是 3(向下取整)</one_and_half_seconds>auto back = std::chrono::duration_cast<:chrono::seconds>(custom); // 得到 4 秒(3 × 1.5 = 4.5 → 截断为 4)</:chrono::seconds>- 推荐在关键路径用
static_cast显式检查是否可表示,或用std::chrono::ceil/std::chrono::round(C++17+)
别名 vs 新类型:用 using 还是 struct?
绝大多数场景用 using 别名即可。只有当你需要重载运算符、添加成员函数,或强制类型隔离(防止意外隐式转换)时,才应继承 std::chrono::duration 定义新类型。
- 普通别名(推荐):
using frame_time = std::chrono::duration<int std::ratio>>;</int>(1/60 秒) - 强类型封装(必要时):
struct frame_duration : std::chrono::duration<int std::ratio>> { using base = std::chrono::duration<int std::ratio>>; constexpr frame_duration(base d) : base(d) {} };</int></int> - 注意:直接继承
std::chrono::duration会导致默认构造、赋值等行为继承,但不会自动继承所有构造函数(C++17 前需手动委托)
std::ratio 当成运行时比例来算,或者误以为自定义单位能绕过 duration_cast 的截断逻辑。它只是换了个周期,底层还是整数除法。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











