我只是想知道我是否应该使用std::size_t for循环之类的东西,而不是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的最佳实践是什么?


当前回答

size_t类型是用来指定某个东西的大小,所以使用它是很自然的,例如,获取一个字符串的长度,然后处理每个字符:

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

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

但要注意以下情况:

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

这将导致一个无限循环,因为无符号值的包装行为(尽管我看到编译器警告反对这一点)。这也可以通过以下方法来缓解(稍难理解,但至少不会受到包装问题的影响):

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

通过将递减转换为延续条件的后检查副作用,这在递减之前对值进行了延续检查,但仍然在循环中使用递减后的值(这就是为什么循环从len ..1而不是镜头1 ..0)。

其他回答

Size_t是unsigned int。所以当你需要unsigned int时,你可以使用它。

我使用它当我想指定数组的大小,计数器等…

void * operator new (size_t size); is a good use of it.

根据定义,size_t是sizeof操作符的结果。创建Size_t是为了引用大小。

你做某事的次数(在你的例子中是10次)与大小无关,那么为什么要使用size_t呢?Int,或者unsigned Int,应该是可以的。

当然,你在循环中对i做什么也是相关的。例如,如果将它传递给一个接受无符号整型的函数,则选择无符号整型。

在任何情况下,我都建议避免隐式类型转换。使所有类型转换显式。

通常最好不要在循环中使用size_t。例如,

vector<int> a = {1,2,3,4};
for (size_t i=0; i<a.size(); i++) {
    std::cout << a[i] << std::endl;
}
size_t n = a.size();
for (size_t i=n-1; i>=0; i--) {
    std::cout << a[i] << std::endl;
}

第一个循环就可以了。但是对于第二个循环: 当i=0时,i——的结果将是ULLONG_MAX(假设size_t = unsigned long long),这不是你在循环中想要的结果。 此外,如果a是空的,那么n=0和n-1=ULLONG_MAX,这也是不好的。

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

为未来做好准备!

Size_t由各种库返回,以指示该容器的大小非零。你用它当你得到一次:0

然而,在上面的例子中,循环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");
}

使用无符号整数有可能产生这类微妙的问题。因此,依我之见,我更喜欢只在与需要size_t的容器/类型交互时使用size_t。