为何std::counting_semaphore<>的模板参数是ptrdiff_t而非size_t
你觉得信号量最大计数值不能为负的直觉完全是对的:C++标准明确要求,实例化std::counting_semaphore<N>时,模板参数N必须满足N >= 0,传入负数的实例化本身就是不符合规范的用法,不会出现在合法代码里。
选择ptrdiff_t而非size_t作为模板参数类型,主要是出于实际工程落地的几个考量:
- 和信号量的操作接口类型统一:
std::counting_semaphore的acquire()、try_acquire()、release()等方法的计数参数类型都定义为ptrdiff_t,模板参数和操作参数保持同类型,可以避免跨类型转换带来的不必要的边界检查开销和隐式类型转换隐患。 - 规避无符号类型的使用陷阱:如果采用无符号的
size_t,当开发者不小心给操作接口传入负数值时,负数会被隐式转换为超大的无符号值,这类错误非常隐蔽,几乎无法在运行时提前拦截;而采用有符号的ptrdiff_t时,接口可以直接对传入的负数参数做合法校验,提前触发断言或者抛出参数错误,大幅降低排查成本。 - 匹配经典的信号量实现逻辑:从Dijkstra提出信号量概念开始,经典的信号量实现就允许中间运行时计数为负,负值的绝对值通常对应当前阻塞等待信号量的线程数,用有符号的
ptrdiff_t可以直接匹配这种实现逻辑,不需要额外做无符号和有符号的转换,也能减少边界判断的性能开销。 - 对齐操作系统原生接口:主流操作系统的原生信号量接口(POSIX信号量、Windows Semaphore等)的计数相关参数普遍采用有符号类型定义,标准库选择
ptrdiff_t可以更方便地封装底层系统接口,减少适配层的转换成本。
内容的提问来源于stack exchange,提问作者Bonita Montero
相关产品推荐
相关产品推荐

