考虑一个典型的绝对值函数(其中为了讨论最大大小的整数类型是长整型):
unsigned long abs(long input);
一个天真的实现可能看起来像:
unsigned long abs(long input)
{
if (input >= 0)
{
// input is positive
// We know this is safe, because the maximum positive signed
// integer is always less than the maximum positive unsigned one
return static_cast<unsigned long>(input);
}
else
{
return static_cast<unsigned long>(-input); // ut oh...
}
}
由于对的否定可能会导致溢出,从而触发有未定义行为。例如,在二进制补码机器上,std :: numeric_limits<long> :: min()
的绝对值将比std :: numeric_limits<long> :: max()
大1个单位。
库的作者可以采取什么措施来解决这个问题?
return x<0 ? 0UL - x : x;
。这使用了在0UL - x
中隐式转换为无符号类型,而不是你的方式明确记录转换发生的时间。显式的方式可能有助于清晰度,尽管你可以使用unsigned long ux = static_cast<unsigned long>(x);
return x<0 : -ux : ux;
仍将其编写为三元运算符,提示编译器以无分支的方式执行。为了避免重复转换,特别是如果你想要模板化以推断输入类型的无符号版本,因此强制转换更长。 - Peter Cordesuabs
或absu
这样的名称比abs
更好。我知道abs
在 C++ 中与std::abs
不同,但对于人类读者来说,这是一个返回无符号值的函数,对于每个输入都是良好定义的,不像不方便的std::abs
和 C 的stdlib.h
中的abs
。 (经常使用 C 和 C++ 的人会倾向于考虑到这一点。) - Peter Cordes