C++ 何时使用 std::size_t?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1951519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:41:59  来源:igfitidea点击:

When to use std::size_t?

c++typesidiomaticsize-tloop-counter

提问by nhaa123

I'm just wondering should I use std::size_tfor loops and stuff instead of int? For instance:

我只是想知道我应该使用std::size_tfor 循环和东西而不是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?
    }
}

In general, what is the best practice regarding when to use std::size_t?

一般来说,关于何时使用的最佳实践是什么std::size_t

采纳答案by CB Bailey

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_titself.

一个好的经验法则是,您需要将循环条件中的任何内容与自然为 a 的内容进行比较std::size_t

std::size_tis the type of any sizeofexpression 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.

std::size_t是任何sizeof表达式的类型,并且保证能够在 C++ 中表达任何对象(包括任何数组)的最大大小。通过扩展,它还保证对于任何数组索引都足够大,因此它是数组上按索引循环的自然类型。

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 intor unsigned int(if large enough) as these should be a natural size for the machine.

如果您只是计算一个数字,那么使用保存该数字的变量类型或intor unsigned int(如果足够大)可能更自然,因为这些应该是机器的自然大小。

回答by Gregory Pakosz

size_tis the result type of the sizeofoperator.

size_tsizeof运算符的结果类型。

Use size_tfor variables that model size or index in an array. size_tconveys semantics: you immediately know it represents a size in bytes or an index, rather than just another integer.

用于size_t对数组中的大小或索引进行建模的变量。size_t传达语义:您立即知道它表示以字节或索引为单位的大小,而不仅仅是另一个整数。

Also, using size_tto represent a size in bytes helps making the code portable.

此外,使用size_t来表示以字节为单位的大小有助于使代码可移植。

回答by paxdiablo

The size_ttype is meant to specify the sizeof something so it's natural to use it, for example, getting the length of a string and then processing each character:

size_t类型旨在指定某物的大小,因此使用它很自然,例如,获取字符串的长度,然后处理每个字符:

for (size_t i = 0, max = strlen (str); i < max; i++)
    doSomethingWith (str[i]);

You dohave 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 ispossible to get there). Most people just use an intfor that sort of thing because they rarely have structures or arrays that get big enough to exceed the capacity of that int.

必须注意,当然边界条件,因为它是一个无符号类型。顶端的边界通常不是那么重要,因为最大值通常很大(尽管可能到达那里)。大多数人只是将 anint用于那种事情,因为他们很少有足够大的结构或数组来超过它的容量int

But watch out for things like:

但请注意以下事项:

for (size_t i = strlen (str) - 1; i >= 0; i--)

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):

由于无符号值的包装行为,这将导致无限循环(尽管我已经看到编译器对此发出警告)。这也可以通过(稍微难以理解但至少不受包装问题的影响)来缓解:

for (size_t i = strlen (str); i-- > 0; )

By shifting the decrement into a post-check side-effect of the continuation condition, this does the check for continuation on the value beforedecrement, but still uses the decremented value inside the loop (which is why the loop runs from len .. 1rather than len-1 .. 0).

通过将递减转换为延续条件的检查后副作用,这会递减之前检查值的延续,但仍使用循环内递减的值(这就是循环从len .. 1而非运行的原因len-1 .. 0)。

回答by Daniel Daranas

By definition, size_tis the result of the sizeofoperator. size_twas created to refer to sizes.

根据定义,size_tsizeof运算符的结果。size_t是为了参考尺寸而创建的。

The number of times you do something (10, in your example) is not about sizes, so why use size_t? int, or unsigned int, should be ok.

您做某事的次数(在您的示例中为 10)与大小无关,那么为什么要使用size_t? int, 或者unsigned int, 应该没问题。

Of course it is also relevant what you do with iinside the loop. If you pass it to a function which takes an unsigned int, for example, pick unsigned int.

当然,这也与您i在循环内执行的操作有关。unsigned int例如,如果您将其传递给采用 的函数,则为 pick unsigned int

In any case, I recommend to avoid implicit type conversions. Make all type conversions explicit.

无论如何,我建议避免隐式类型转换。使所有类型转换显式。

回答by Ofir

size_tis 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 that unsigned intmight not do (e.g. when should you use unsigned long

size_t是一种非常易读的方式来指定项目的大小维度 - 字符串的长度、指针占用的字节数等。它也可以跨平台移植 - 你会发现 64 位和 32 位都与系统函数表现良好,并且size_t-一些unsigned int可能不会做的事情(例如你应该什么时候使用unsigned long

回答by Arne

short answer:

简短的回答:

almost never

几乎从不

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.

每当您需要在 32 位系统上使用大于 2gb 的字符向量时。在所有其他用例中,使用有符号类型比使用无符号类型安全得多。

example:

例子:

std::vector<A> data;
[...]
// calculate the index that should be used;
size_t i = calc_index(param1, param2);
// doing calculations close to the underflow of an integer is already dangerous

// do some bounds checking
if( i - 1 < 0 ) {
    // always false, because 0-1 on unsigned creates an underflow
    return LEFT_BORDER;
} else if( i >= data.size() - 1 ) {
    // if i already had an underflow, this becomes true
    return RIGHT_BORDER;
}

// now you have a bug that is very hard to track, because you never 
// get an exception or anything anymore, to detect that you actually 
// return the false border case.

return calc_something(data[i-1], data[i], data[i+1]);

The signed equivalent of size_tis ptrdiff_t, not int. But using intis still much better in most cases than size_t. ptrdiff_tis longon 32 and 64 bit systems.

有符号的等价物size_tptrdiff_t,不是int。但是int在大多数情况下使用仍然比 size_t 好得多。ptrdiff_tlong在32个64位系统。

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.

这意味着每当您与 std::containers 交互时,您总是必须在 size_t 之间进行转换,这不是很漂亮。但是在一次本地会议上,c++ 的作者提到用无符号 size_t 设计 std::vector 是一个错误。

If your compiler gives you warnings on implicit conversions from ptrdiff_t to size_t, you can make it explicit with constructor syntax:

如果您的编译器对从 ptrdiff_t 到 size_t 的隐式转换发出警告,您可以使用构造函数语法使其显式:

calc_something(data[size_t(i-1)], data[size_t(i)], data[size_t(i+1)]);

if just want to iterate a collection, without bounds cheking, use range based for:

如果只想迭代一个集合,没有边界检查,请使用基于范围的:

for(const auto& d : data) {
    [...]
}

here some words from Bjarne Stroustrup (C++ author) at going native

这里是一些从Bjarne的Stroustrup的(C ++的作者)的话去本地

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.

对于某些人来说,STL 中的这个有符号/无符号设计错误就足够了,不使用 std::vector,而是使用自己的实现。

回答by Peter Alexander

Use std::size_t for indexing/counting C-style arrays.

使用 std::size_t 索引/计数 C 样式数组。

For STL containers, you'll have (for example) vector<int>::size_type, which should be used for indexing and counting vector elements.

对于 STL 容器,您将拥有(例如)vector<int>::size_type,它应该用于索引和计算向量元素。

In practice, they are usually both unsigned ints, but it isn't guaranteed, especially when using custom allocators.

实际上,它们通常都是无符号整数,但不能保证,尤其是在使用自定义分配器时。

回答by Nordl?w

Soon most computers will be 64-bit architectures with 64-bit OS:es running programs operating on containers of billions of elements. Then you mustuse size_tinstead of intas loop index, otherwise your index will wrap aroundat the 2^32:th element, on both 32- and 64-bit systems.

很快,大多数计算机将采用 64 位体系结构,在 64 位操作系统上运行在数十亿个元素的容器上运行的程序。然后您必须使用size_t而不是int作为循环索引,否则您的索引将在 2^32:th 元素处环绕,在 32 位和 64 位系统上。

Prepare for the future!

为未来做好准备!

回答by Kemin Zhou

When using size_t be careful with the following expression

使用 size_t 时请注意以下表达式

size_t i = containner.find("mytoken");
size_t x = 99;
if (i-x>-1 && i+x < containner.size()) {
    cout << containner[i-x] << " " << containner[i+x] << endl;
}

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.

无论 x 的值是什么,if 表达式中都会得到 false。我花了好几天才意识到这一点(代码很简单,我没有做单元测试),虽然只花了几分钟就找出问题的根源。不确定最好进行演员表还是使用零。

if ((int)(i-x) > -1 or (i-x) >= 0)

Both ways should work. Here is my test run

两种方式都应该有效。这是我的测试运行

size_t i = 5;
cerr << "i-7=" << i-7 << " (int)(i-7)=" << (int)(i-7) << endl;

The output: i-7=18446744073709551614 (int)(i-7)=-2

输出: i-7=18446744073709551614 (int)(i-7)=-2

I would like other's comments.

我想要其他人的评论。

回答by ascotan

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

size_t 由各种库返回,以指示该容器的大小非零。当你回来时使用它:0

However, in the your example above looping on a size_t is a potential bug. Consider the following:

但是,在上面的示例中,循环 size_t 是一个潜在的错误。考虑以下:

for (size_t i = thing.size(); i >= 0; --i) {
  // this will never terminate because size_t is a typedef for
  // unsigned int which can not be negative by definition
  // therefore i will always be >= 0
  printf("the never ending story. la la la la");
}

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。