C++什么时候需要'int'?
When do you need 'int' in C++?
我确实意识到这个标题一开始听起来可能很傻,但请耐心等待。:)
自从我开始使用size_t
和ptrdiff_t
以来,就我记忆所及,我还没有使用过int
。
我记得最近使用的唯一整数数据类型属于以下类别之一:
-
(无符号)整数,与内存中某些数据结构(例如
vector
)的索引相关
几乎总是,最合适的类型是size_t
(或者...::size_type
,如果你要多走一步的话)
即使整数实际上并不表示索引,但通常情况下它仍然与某个索引相关,因此size_t
仍然是合适的。 -
size_t
的签名版本。在许多情况下,最适合的类型似乎是ptrdiff_t
,因为通常当您需要它时,您会使用迭代器——因此size_t
和ptrdiff_t
都适合它们。 -
long
。我偶尔需要_InterlockedIncrement
(参考计数)。 -
(
unsigned
)long long
,用于保持文件大小。 -
unsigned int
或unsigned long
,用于"计数"目的(例如,每100万次迭代,更新UI)。 -
CCD_ 18用于对存储器的原始字节级访问
(旁注:我也从未发现signed char
的用途。) -
intptr_t
和uintptr_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
符合要求。
- 什么时候调用组成单元对象的析构函数
- 什么时候在C++中返回常量引用是个好主意
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 编译器对数组声明大小的计算。什么时候发生?
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 您应该在什么时候创建自己的异常类型
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 什么时候可以使用常量装饰调用我的重载函数?
- unordered_map什么时候返回 -1?
- QCoreApplication什么时候有效?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 如果真的需要std::move,我们应该什么时候声明右值refs
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- 程序什么时候会创建多个堆
- 调用boost.asio的异步函数时,线程是什么时候创建的
- C++什么时候需要'int'?
- 什么时候应该使用 vector<int>::size_type 而不是 size_t?