问题很清楚。
我想知道为什么他们认为这会很方便,显然负索引在与其一起使用的容器中是无法使用的(例如请参见QList
的文档)。
我原以为他们想要允许某种疯狂的索引方式,但似乎并不支持?
它还会生成大量(正确的)编译器警告,涉及到有符号/无符号类型之间的强制转换和比较(在MSVC上)。
总之,由于某种原因,它似乎与STL不兼容...
尽管我深表同情Chris的思路,但在这里我要不同意他(至少在某些方面上,我是在担任魔鬼的代言人)。 对于使用无符号类型存储大小没有任何问题,甚至在某些情况下是有益的。
Chris使用有符号大小类型的理由是它们自然用作数组索引,您可能想对数组索引进行算术运算,而该算术运算可能会创建临时值为负数。
那没关系,使用无符号算术运算时也不会有任何问题,只要在比较时正确地解释您的值即可。 因为无符号整数的溢出行为是完全指定的,所以临时溢出到负范围(或巨大正数)不会引入任何错误,只要在执行比较之前进行纠正即可。
有时,溢出行为甚至是可取的,因为无符号算术的溢出行为使得某些范围检查可表示为单个比较,否则需要两个比较。 如果我想检查x
是否在范围[a,b]
内,并且所有值都是无符号的,则可以简单地执行以下操作:
if (x - a < b - a) {
}
这不适用于带符号变量;这种范围检查在大小和数组偏移量中非常常见。
之前我提到的一个好处是溢出算术具有定义的结果。如果您的索引算术溢出了带符号类型,行为是实现定义的;没有办法使您的程序可移植。使用无符号类型,这个问题就会消失。当然,这仅适用于极大的偏移量,但对于某些用途来说,这是一个问题。
基本上,对无符号类型的反对意见经常被夸大了。真正的问题是,大多数程序员并没有真正考虑他们编写的代码的确切语义,对于小的整数值,带符号类型的行为更接近他们的直觉。然而,数据大小增长得相当快。当我们处理缓冲区或数据库时,我们经常远离“小”的范围,带符号溢出比无符号溢出更难正确处理。解决方案不是“不使用无符号类型”,而是“仔细考虑您正在编写的代码,并确保您理解它”。
由于实际上通常需要对索引执行算术运算,这意味着您可能希望创建负数临时变量。但是,当底层索引类型为无符号时,这显然是痛苦的。
使用无符号数字的唯一适当时间是进行模数算术。将“无符号”用作某种契约说明符“范围为[0...”就很笨拙,而且太粗糙,无法使用。
考虑:我应该使用什么类型来表示该数字应为介于1和10之间的正整数?为什么是0...2^x一个更特殊的范围?