何时使用 std::size_t?
我只是想知道我应该使用 std::size_t
进行循环和其他内容而不是 int
吗? 例如:
#include <cstdint>
int main()
{
for (std::size_t i = 0; i < 10; ++i) {
// std::size_t OK here? Or should I use, say, unsigned int instead?
}
}
一般来说,何时使用 std::size_t 的最佳实践是什么?
I'm just wondering should I use std::size_t
for loops and stuff instead of int
?
For instance:
#include <cstdint>
int main()
{
for (std::size_t i = 0; i < 10; ++i) {
// std::size_t OK here? Or should I use, say, unsigned int instead?
}
}
In general, what is the best practice regarding when to use std::size_t
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
一个好的经验法则是,您需要在循环条件中与自然是
std::size_t
本身的内容进行比较。std::size_t
是任何sizeof
表达式的类型,并且 as 保证能够表达 C++ 中任何对象(包括任何数组)的最大大小。通过扩展,它还保证对于任何数组索引都足够大,因此它是数组上按索引循环的自然类型。如果您只是计算一个数字,那么使用保存该数字的变量类型或
int
或unsigned int
可能更自然(如果很大的话)足够),因为这些应该是机器的自然尺寸。A good rule of thumb is for anything that you need to compare in the loop condition against something that is naturally a
std::size_t
itself.std::size_t
is the type of anysizeof
expression and as is guaranteed to be able to express the maximum size of any object (including any array) in C++. By extension it is also guaranteed to be big enough for any array index so it is a natural type for a loop by index over an array.If you are just counting up to a number then it may be more natural to use either the type of the variable that holds that number or an
int
orunsigned int
(if large enough) as these should be a natural size for the machine.size_t
是sizeof
运算符的结果类型。使用
size_t
作为对数组中的大小或索引进行建模的变量。size_t
传达语义:您立即知道它代表字节大小或索引,而不仅仅是另一个整数。此外,使用
size_t
表示字节大小有助于使代码可移植。size_t
is the result type of thesizeof
operator.Use
size_t
for variables that model size or index in an array.size_t
conveys semantics: you immediately know it represents a size in bytes or an index, rather than just another integer.Also, using
size_t
to represent a size in bytes helps making the code portable.size_t
类型旨在指定某些内容的大小,因此使用它是很自然的,例如,获取字符串的长度,然后处理每个字符:您当然必须注意边界条件,因为它是无符号类型。顶端的边界通常并不那么重要,因为最大值通常很大(尽管有可能到达那里)。大多数人只是使用
int
来处理这类事情,因为他们很少有足够大的结构或数组来超出该int
的容量。但请注意以下情况:
由于无符号值的包装行为,这将导致无限循环(尽管我已经看到编译器对此发出警告)。这也可以通过以下方式来缓解(稍微难以理解,但至少不受包装问题的影响):
通过将减量转移到连续条件的检查后副作用中,这会检查值 的连续性在递减之前,但仍然在循环内使用递减后的值(这就是循环从
len .. 1
而不是len-1 .. 0
运行的原因)。The
size_t
type is meant to specify the size of something so it's natural to use it, for example, getting the length of a string and then processing each character:You do have to watch out for boundary conditions of course, since it's an unsigned type. The boundary at the top end is not usually that important since the maximum is usually large (though it is possible to get there). Most people just use an
int
for that sort of thing because they rarely have structures or arrays that get big enough to exceed the capacity of thatint
.But watch out for things like:
which will cause an infinite loop due to the wrapping behaviour of unsigned values (although I've seen compilers warn against this). This can also be alleviated by the (slightly harder to understand but at least immune to wrapping problems):
By shifting the decrement into a post-check side-effect of the continuation condition, this does the check for continuation on the value before decrement, but still uses the decremented value inside the loop (which is why the loop runs from
len .. 1
rather thanlen-1 .. 0
).根据定义,
size_t
是sizeof
运算符的结果。size_t
的创建是为了引用尺寸。你做某事的次数(在你的例子中是 10 次)与大小无关,那么为什么要使用
size_t
呢?int
或unsigned int
应该没问题。当然,这也与您在循环内使用
i
执行的操作有关。例如,如果将其传递给采用unsigned int
的函数,请选择unsigned int
。无论如何,我建议避免隐式类型转换。 明确所有类型转换。
By definition,
size_t
is the result of thesizeof
operator.size_t
was created to refer to sizes.The number of times you do something (10, in your example) is not about sizes, so why use
size_t
?int
, orunsigned int
, should be ok.Of course it is also relevant what you do with
i
inside the loop. If you pass it to a function which takes anunsigned int
, for example, pickunsigned int
.In any case, I recommend to avoid implicit type conversions. Make all type conversions explicit.
简短的回答:
几乎从不。使用签名版本
ptrdiff_t
或非标准ssize_t
。使用函数std::ssize
而不是std::size
。长答案:
每当您需要在 32 位系统上拥有大于 2GB 的 char 向量时。在所有其他用例中,使用有符号类型比使用无符号类型安全得多。
例如:
size_t
的有符号等价物是ptrdiff_t
,而不是int
。但在大多数情况下使用 int 仍然比 size_t 要好得多。ptrdiff_t
在 32 位和 64 位系统上为long
。这意味着每当与 std::containers 交互时,您总是必须在 size_t 之间进行转换,这不太美观。但在一次本地会议上,c++ 的作者提到用无符号 size_t 设计 std::vector 是一个错误。
如果您的编译器向您发出有关从 ptrdiff_t 到 size_t 的隐式转换的警告,您可以使用构造函数语法将其显式显示:
如果只想迭代集合而不进行边界检查,请使用基于范围的 for:
这里是 Bjarne Stroustrup(C++ 作者)的一些话走向原生
对于某些人来说,这个签名/未签名的设计错误STL 有足够的理由不使用 std::vector,而是使用自己的实现。
short answer:
Almost never. Use signed version
ptrdiff_t
or non-standardssize_t
. Use functionstd::ssize
instead ofstd::size
.long answer:
Whenever you need to have a vector of char bigger that 2gb on a 32 bit system. In every other use case, using a signed type is much safer than using an unsigned type.
example:
The signed equivalent of
size_t
isptrdiff_t
, notint
. But usingint
is still much better in most cases than size_t.ptrdiff_t
islong
on 32 and 64 bit systems.This means that you always have to convert to and from size_t whenever you interact with a std::containers, which not very beautiful. But on a going native conference the authors of c++ mentioned that designing std::vector with an unsigned size_t was a mistake.
If your compiler gives you warnings on implicit conversions from ptrdiff_t to size_t, you can make it explicit with constructor syntax:
if just want to iterate a collection, without bounds cheking, use range based for:
here some words from Bjarne Stroustrup (C++ author) at going native
For some people this signed/unsigned design error in the STL is reason enough, to not use the std::vector, but instead an own implementation.
size_t
是一种非常易读的方式来指定项目的大小维度 - 字符串的长度、指针占用的字节数等。它也可以跨平台移植 - 您会发现 64 位和 32 位都可以很好地处理系统函数和
size_t
- 这是unsigned int
可能不会做的事情(例如,什么时候应该使用无符号长
size_t
is a very readable way to specify the size dimension of an item - length of a string, amount of bytes a pointer takes, etc.It's also portable across platforms - you'll find that 64bit and 32bit both behave nicely with system functions and
size_t
- something thatunsigned int
might not do (e.g. when should you useunsigned long
使用 std::size_t 来索引/计数 C 样式数组。
对于 STL 容器,您将拥有(例如)
vector::size_type
,它应用于向量元素的索引和计数。在实践中,它们通常都是无符号整数,但这并不能保证,特别是在使用自定义分配器时。
Use std::size_t for indexing/counting C-style arrays.
For STL containers, you'll have (for example)
vector<int>::size_type
, which should be used for indexing and counting vector elements.In practice, they are usually both unsigned ints, but it isn't guaranteed, especially when using custom allocators.
很快,大多数计算机将采用 64 位架构,并配备 64 位操作系统,运行在包含数十亿个元素的容器上运行的程序。那么你必须使用
size_t
而不是int
作为循环索引,否则你的索引将在2^处环绕第 32 个元素,在 32 位和 64 位系统上均如此。为未来做好准备!
Soon most computers will be 64-bit architectures with 64-bit OS:es running programs operating on containers of billions of elements. Then you must use
size_t
instead ofint
as loop index, otherwise your index will wrap around at the 2^32:th element, on both 32- and 64-bit systems.Prepare for the future!
size_t 由各种库返回,以指示该容器的大小非零。当你回来时你使用它:0
但是,在上面的示例中,在 size_t 上循环是一个潜在的错误。请考虑以下事项:
使用无符号整数有可能产生这些类型的微妙问题。因此,恕我直言,我更喜欢仅在与需要它的容器/类型交互时才使用 size_t 。
size_t is returned by various libraries to indicate that the size of that container is non-zero. You use it when you get once back :0
However, in the your example above looping on a size_t is a potential bug. Consider the following:
the use of unsigned integers has the potential to create these types of subtle issues. Therefore imho I prefer to use size_t only when I interact with containers/types that require it.
使用 size_t 时请注意以下表达式
无论 x 的值是什么,if 表达式中都会得到 false。
我花了几天时间才意识到这一点(代码太简单了,我没有做单元测试),尽管只花了几分钟就找出了问题的根源。不确定是进行强制转换还是使用零更好。
两种方法都应该有效。这是我的测试运行
输出: i-7=18446744073709551614 (int)(i-7)=-2
我想听听其他人的评论。
When using size_t be careful with the following expression
You will get false in the if expression regardless of what value you have for x.
It took me several days to realize this (the code is so simple that I did not do unit test), although it only take a few minutes to figure the source of the problem. Not sure it is better to do a cast or use zero.
Both ways should work. Here is my test run
The output: i-7=18446744073709551614 (int)(i-7)=-2
I would like other's comments.
通常最好不要在循环中使用 size_t。例如,
第一个循环就可以了。但对于第二个循环:
当 i=0 时,i-- 的结果将为 ULLONG_MAX(假设 size_t = unsigned long long),这不是您想要的循环结果。
此外,如果 a 为空,则 n=0 且 n-1=ULLONG_MAX 这也不好。
It is often better not to use size_t in a loop. For example,
The first loop is ok. But for the second loop:
When i=0, the result of i-- will be ULLONG_MAX (assuming size_t = unsigned long long), which is not what you want in a loop.
Moreover, if a is empty then n=0 and n-1=ULLONG_MAX which is not good either.
size_t
是一种无符号类型,可以容纳架构的最大整数值,因此可以防止由于符号而导致的整数溢出(有符号 int0x7FFFFFFF
加 1 会得到 - 1) 或短大小(无符号短整型 0xFFFF 加 1 将得到 0)。主要用于数组索引/循环/地址运算等。像
memset()
之类的函数仅接受size_t
,因为理论上您可能有一个大小为2^32-1
的内存块(在32位平台)。对于如此简单的循环,不必费心,只需使用 int 即可。
size_t
is an unsigned type that can hold maximum integer value for your architecture, so it is protected from integer overflows due to sign (signed int0x7FFFFFFF
incremented by 1 will give you -1) or short size (unsigned short int 0xFFFF incremented by 1 will give you 0).It is mainly used in array indexing/loops/address arithmetic and so on. Functions like
memset()
and alike acceptsize_t
only, because theoretically you may have a block of memory of size2^32-1
(on 32bit platform).For such simple loops don't bother and use just int.
我一直在努力理解什么以及何时使用它。但 size_t 只是一个无符号整数数据类型,在各种头文件中定义,例如
、、、、< ;time.h>、
等。它用于表示对象的大小(以字节为单位),因此它被 sizeof 运算符用作返回类型。允许的最大大小取决于编译器;如果编译器是 32 位,那么它只是 unsigned int 的 typedef(别名),但如果编译器是 64 位,那么它将是 unsigned long long 的 typedef。 size_t 数据类型永远不会为负(不包括 ssize_t)
因此,许多 C 库函数(例如
malloc、memcpy 和 strlen
)将其参数和返回类型声明为size_t
。size_t
或任何无符号类型都可能被视为用作循环变量,因为循环变量通常大于或等于 0。I have been struggling myself with understanding what and when to use it. But size_t is just an unsigned integral data type which is defined in various header files such as
<stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, <time.h>, <wchar.h>
etc.It is used to represent the size of objects in bytes hence it's used as the return type by the sizeof operator. The maximum permissible size is dependent on the compiler; if the compiler is 32 bit then it is simply a typedef (alias) for unsigned int but if the compiler is 64 bit then it would be a typedef for unsigned long long. The size_t data type is never negative(excluding ssize_t)
Therefore many C library functions like
malloc, memcpy and strlen
declare their arguments and return type assize_t
.size_t
or any unsigned type might be seen used as loop variable as loop variables are typically greater than or equal to 0.size_t 是无符号整数类型,可以表示系统上最大的整数。
仅当您需要非常大的数组、矩阵等时才使用它。
某些函数返回 size_t,如果您尝试进行比较,编译器会警告您。
通过使用适当的有符号/无符号数据类型或简单地进行快速破解来避免这种情况。
size_t is an unsigned integral type, that can represent the largest integer on you system.
Only use it if you need very large arrays,matrices etc.
Some functions return an size_t and your compiler will warn you if you try to do comparisons.
Avoid that by using a the appropriate signed/unsigned datatype or simply typecast for a fast hack.
size_t 是无符号整数。所以只要你想要 unsigned int 就可以使用它。
当我想指定数组的大小、计数器等时我使用它......
size_t is unsigned int. so whenever you want unsigned int you can use it.
I use it when i want to specify size of the array , counter ect...