C++什么时候需要'int'?

When do you need 'int' in C++?

本文关键字:int 什么时候 C++      更新时间:2023-10-16

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

自从我开始使用size_tptrdiff_t以来,就我记忆所及,我还没有使用过int

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

  1. (无符号)整数,与内存中某些数据结构(例如vector)的索引相关
    几乎总是,最合适的类型是size_t(或者...::size_type,如果你要多走一步的话)
    即使整数实际上并不表示索引,但通常情况下它仍然与某个索引相关,因此size_t仍然是合适的。

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

  3. long。我偶尔需要_InterlockedIncrement(参考计数)。

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

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

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

  7. intptr_tuintptr_t,用于偶尔存储操作系统句柄、指针等

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

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

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

long weeklyHours = daysWorked * hoursPerDay;

"好吧……但话说回来,一个人每周实际能工作多少,我们需要long">

size_t weeklyHours = daysWorked * hoursPerDay;

"等等…我们是在使用weeklyHours迭代向量吗?">

unsigned int weeklyHours = daysWorked * hoursPerDay;

"足够清楚。">-错误的可能来源,如果其中一个可能是负的(逻辑的一部分-这可能是一种解释休假或离开的方式,不重要)

int weeklyHours = daysWorked * hoursPerDay;

"好吧,很简单。我明白这是怎么回事。">

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周期方面很便宜,通用积分存储的首选类型也是如此。如果你开始使用unsigned char来存储某人的年龄,它不仅不能很好地与operator<<(std::ostream&...)配合使用,而且会引发一些问题,比如"这里是否需要保存内存?"(对于基于堆栈的变量来说尤其令人困惑),"是否有将其视为I/O或IPC目的的二进制数据的意图?",甚至"这是存储在ASCII中的已知个位数年龄吗?"。如果某种东西最终可能会出现在寄存器中,那么int是一个自然大小。

假设您正在为一个银行帐户实现一个程序。如果你提取了太多(有些账户允许你提取,并会受到处罚),那么你需要以某种方式表示负值。

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

int是存储整数对数的完美候选者,例如地图上的缩放级别。

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