【问题标题】:When do you need 'int' in C++?什么时候需要 C++ 中的“int”?
【发布时间】:2012-12-05 06:51:02
【问题描述】:

我确实意识到这个标题一开始可能听起来很傻,但是请耐心等待我一会儿。 :)

自从我开始使用size_t 和ptrdiff_t 以来,我就再也没有使用过int,直到我记得。

我记得最近使用的唯一整数数据类型属于以下类别之一:

  1. (无符号)与某个内存数据结构(例如vector)的索引相关联的整数。
    几乎总是,最合适的类型是size_t(或...::size_type,如果您要加倍努力)。
    即使整数实际上不代表一个索引,但通常它仍然关联某个索引,所以size_t仍然是合适的。

  2. size_t 的签名版本。在许多情况下,最合适的类型似乎是ptrdiff_t,因为通常当您需要它时,您正在使用迭代器——因此size_t 和ptrdiff_t 都适合它们。

  3. long。 _InterlockedIncrement 偶尔需要这个(引用计数)。

  4. (unsigned) long long,用于保存文件大小。

  5. unsigned int 或 unsigned long,用于“计数”目的(例如,每 100 万次迭代,更新 UI)。

  6. unsigned char 用于对内存的原始字节级访问。
    (旁注:我也从未发现signed char 的用途。)

  7. intptr_t 和 uintptr_t 用于偶尔存储操作系统句柄、指针等。

int 的一个重要方面是你不应该溢出它(因为它是未定义的行为),所以你甚至不能可靠地使用它来进行计数——特别是如果你的编译器将它定义为 16 位.

那么,你应该在什么时候使用int(除了你的依赖项已经需要它的时候)?
现在它有什么实际用途吗,至少在新编写的可移植代码中?

【问题讨论】:

  • 定义operator++(int)时? :)
  • 请阅读:stackoverflow.com/questions/739727/… TL;DR:int 是内置类型,size_t 是define,int 可以表示负数,这对...数学有用吗?说真的。
  • @KSchmidt 无论编译成什么,它仍然是一个 unsigned 类型。
  • @Yuushi 我没有说相反的话。但是“size_t 的签名版本”根本没有任何意义。这个问题也没有任何意义——当然有符号值很有用!当您进行数学运算并且需要表示有符号值时,例如 x/y 位置等
  • @KSchmidt 我怀疑size_t 和ptrdiff_t 在大多数实现中都被定义为(unsigned) int。 long,是的(在 64 位 Windows 上除外)。

标签: c++ int


【解决方案1】:

我自己终于找到了一个很好的用例:

int 是存储整数对数的理想选择,例如地图上的缩放级别。

short 通常对此没有足够的精度(平滑鼠标滚轮的旋转可能非常精确),而long 通常比我们需要的精度更高。
我们肯定需要负值,所以我们不应该使用无符号类型。因此int 符合要求。

【讨论】:

    【解决方案2】:

    Luchian 有一些优秀的可读性点,我将添加一些技术点:

    • 编译器希望为int 选择一个可以有效处理的大小,而long 可能不是(每个操作可能会占用更多 CPU 周期、更多字节的机器代码、需要更多寄存器等)
    • 使用有符号类型可以消除一些错误,例如:
      • abs(a - b) 在数学上看起来是正确的,但当 b > a 并且它们没有签名时,并没有给出直观的结果
      • int second_delta = (x.seconds - y.seconds) + (x.minutes - y.minutes) * 60;
      • if (pending - completed > 1) kick_off_threads()
    • 当需要整数标记值时,经常使用-1:对于无符号类型,这将被转换为可能的最大值,但这可能会导致误解和编码错误(例如if (x >= 0) 测试非标记)

    此外,有符号整数和无符号整数之间的隐式转换有很多范围 - 重要的是要了解无符号类型很少有助于强制执行“非负”不变量:如果这是吸引力的一部分,那么最好写具有强制执行不变量的构造函数和运算符的类。

    在可读性方面,int 表示一般需要一个明确跨越问题域的数字 - 它可能过多,但已知它在机器代码操作和 CPU 周期方面很便宜,因此一般积分的首选类型贮存。如果您开始使用say unsigned char 来存储某人的年龄 - 它不仅不能很好地与operator<<(std::ostream&...) 配合使用,而且还会引发诸如“这里是否需要保存内存?”之类的问题。 (尤其是对基于堆栈的变量感到困惑),“是否有意将其视为用于 I/O 或 IPC 目的的二进制数据?”,甚至“它是存储在 ASCII 中的已知个位数年龄吗?”。如果某些东西最终可能会出现在寄存器中,int 是一个自然的大小。

    【讨论】:

    • +1 表示abs(a-b)。我曾经遇到过类似于错误的事情。我花了很长时间才弄明白出了什么问题。
    【解决方案3】:

    假设您正在为一个银行帐户实施一个程序。如果您提款过多(某些账户允许您提款,但会受到处罚),那么您将需要以某种方式表示负值。

    【讨论】:

    • IMO 银行账户应使用long long,例如当前的美国预算等。 =P
    • @LuchianGrigore 那么有什么问题呢?一种单符号变量类型?大量的#define'd 类型是基于的,但是没有人对这些有问题吗?完全令人困惑。
    • @KSchmidt 是的,我想是的。该操作提供long 作为替代,已签名。
    【解决方案4】:

    最重要的原因是什么 - 可读性。 (和简单的数学)

    long weeklyHours = daysWorked * hoursPerDay;
    

    “好吧……不过话说回来,我们需要long”

    size_t weeklyHours = daysWorked * hoursPerDay;
    

    “等等...我们是在使用weeklyHours 来迭代向量吗?”

    unsigned int weeklyHours = daysWorked * hoursPerDay;
    

    “足够清楚。” - 如果其中一个可能是负数,则可能是错误的来源(逻辑的一部分 - 这可能是一种考虑休假或休假的方法,并不重要)

    int weeklyHours = daysWorked * hoursPerDay;
    

    “好的,很简单。我明白这是做什么的。”

    【讨论】:

    • 我不明白,这不应该使用unsigned int吗?当你的代码中不应该有否定时,为什么要允许否定?
    • 我想说unsigned weeklyHours = daysWorked * hoursPerDay; 对我来说是最易读的,但我可以看到这可能会被争论,所以+1。不过还是希望有更说服力的。 ;)
    • @Mehrdad 虽然我知道使用unsigned 的优点,但我个人只会考虑溢出/位操作。
    • @Mehrdad 我同意 Luchian 的观点,无符号值溢出,你不会知道它发生了 - 如果你的无符号值是 0,并且你至少减去 1,那么它是一个巨大的数字。对于大多数用法,int 具有足够的值范围表示,并且没有“哎呀,我减去了一个,现在我有一个巨大的数字”的问题。
    • @Mehrdad:在一般用法中,int 可能会溢出,而unsigned 本来是安全的,此时只需要大约 2^31...2^32 的额外值。 . 这比在 0 的“错误”一侧生成(即使只是表达式中的临时变量)值要少得多。
    猜你喜欢
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    • 2011-07-07
    • 2017-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多