我只是想知道我是否应该使用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的最佳实践是什么?


当前回答

一个很好的经验法则是,对于需要在循环条件中与std::size_t本身的东西进行比较的任何东西。

std::size_t是任何sizeof表达式的类型,as被保证能够在c++中表示任何对象(包括任何数组)的最大大小。通过扩展,它也保证足够大,可以用于任何数组下标,因此它是数组上按下标循环的自然类型。

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

其他回答

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

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

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

简短的回答:

几乎没有。使用signed版本ptrdiff_t或非标准的ssize_t。使用函数std::ssize代替std::size。

长一点的回答:

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

例子:

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]);

size_t的等效符号是ptrdiff_t,而不是int。但在大多数情况下,使用int仍然比使用size_t要好得多。Ptrdiff_t在32位和64位系统上是长值。

这意味着无论何时与std::容器交互,都必须从size_t转换到size_t,这不是很漂亮。但是在一个正在进行的本地会议上,c++的作者提到,用无符号的size_t来设计std::vector是一个错误。

如果你的编译器给出了从ptrdiff_t到size_t的隐式转换的警告,你可以通过构造函数语法将其显式化:

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

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

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

这里是Bjarne Stroustrup (c++作者)关于本地化的一些话

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

使用std::size_t对c风格数组进行索引/计数。

对于STL容器,你会有(例如)vector<int>::size_type,它应该用于索引和计数vector元素。

实际上,它们通常都是无符号整型,但这并不能保证,特别是在使用自定义分配器时。

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

size_t是一种无符号类型,它可以为您的体系结构保存最大整数值,因此它不会因为符号(有符号int 0x7FFFFFFF加1会得到-1)或短大小(无符号短int 0xFFFF加1会得到0)而导致整数溢出。

它主要用于数组索引/循环/地址算法等。像memset()这样的函数只接受size_t,因为理论上你可能有一个大小为2^32-1的内存块(在32位平台上)。

对于这样简单的循环,不要麻烦,只使用int。