为什么Qt在其容器类中使用有符号整数类型?

11

问题很清楚。

我想知道为什么他们认为这会很方便,显然负索引在与其一起使用的容器中是无法使用的(例如请参见QList的文档)。

我原以为他们想要允许某种疯狂的索引方式,但似乎并不支持?

它还会生成大量(正确的)编译器警告,涉及到有符号/无符号类型之间的强制转换和比较(在MSVC上)。

总之,由于某种原因,它似乎与STL不兼容...

2个回答

12

尽管我深表同情Chris的思路,但在这里我要不同意他(至少在某些方面上,我是在担任魔鬼的代言人)。 对于使用无符号类型存储大小没有任何问题,甚至在某些情况下是有益的。

Chris使用有符号大小类型的理由是它们自然用作数组索引,您可能想对数组索引进行算术运算,而该算术运算可能会创建临时值为负数。

那没关系,使用无符号算术运算时也不会有任何问题,只要在比较时正确地解释您的值即可。 因为无符号整数的溢出行为是完全指定的,所以临时溢出到负范围(或巨大正数)不会引入任何错误,只要在执行比较之前进行纠正即可。

有时,溢出行为甚至是可取的,因为无符号算术的溢出行为使得某些范围检查可表示为单个比较,否则需要两个比较。 如果我想检查x是否在范围[a,b]内,并且所有值都是无符号的,则可以简单地执行以下操作:

if (x - a < b - a) {
}

这不适用于带符号变量;这种范围检查在大小和数组偏移量中非常常见。

之前我提到的一个好处是溢出算术具有定义的结果。如果您的索引算术溢出了带符号类型,行为是实现定义的;没有办法使您的程序可移植。使用无符号类型,这个问题就会消失。当然,这仅适用于极大的偏移量,但对于某些用途来说,这是一个问题。

基本上,对无符号类型的反对意见经常被夸大了。真正的问题是,大多数程序员并没有真正考虑他们编写的代码的确切语义,对于的整数值,带符号类型的行为更接近他们的直觉。然而,数据大小增长得相当快。当我们处理缓冲区或数据库时,我们经常远离“小”的范围,带符号溢出比无符号溢出更难正确处理。解决方案不是“不使用无符号类型”,而是“仔细考虑您正在编写的代码,并确保您理解它”。


我确实喜欢使用无符号索引进行懒惰下溢检查的风格。 - Chris Becke
@stephen. 你的意思是 (x - a < b - a) 吗?这类似于检查有符号值是否在区间 [0,b] 内的技巧(unsigned(x) < b)就足够了。 - Stephen Kennedy
@StephenKennedy 是的。 - Stephen Canon

4

由于实际上通常需要对索引执行算术运算,这意味着您可能希望创建负数临时变量。但是,当底层索引类型为无符号时,这显然是痛苦的。

使用无符号数字的唯一适当时间是进行模数算术。将“无符号”用作某种契约说明符“范围为[0...”就很笨拙,而且太粗糙,无法使用。

考虑:我应该使用什么类型来表示该数字应为介于1和10之间的正整数?为什么是0...2^x一个更特殊的范围?


3
那里的“only”是一个相当强的限定词。 - Sapph
2
我同意更一般的观点,即无符号类型在其常用的文档角色中被高估了。 - Steve Jessop
2
@Steve 使用任何非 char 类型意味着,在有符号量环绕的时候,无符号量将会索引超过可用内存(并环绕)。无论索引是有符号还是无符号,最终结果都相同:某个“随机”的内存位置被索引。 - Chris Becke
1
"size_t被认为是有害的" :P - Chris Becke
1
接受,因为评论讨论非常有趣 :) - rubenvb
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接