我只是想知道我是否应该使用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 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的最佳实践是什么?
当前回答
很快,大多数计算机将是64位体系结构,带有64位操作系统,运行在数十亿个元素的容器上的程序。然后必须使用size_t而不是int作为循环索引,否则在32位和64位系统上,索引将在2^32:th元素处换行。
为未来做好准备!
其他回答
我一直在努力理解什么时候使用它。但size_t只是一个无符号整型数据类型,它定义在各种头文件中,如<stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, <time.h>, <wchar.h>等。
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 as size_t.
/ Declaration of various standard library functions.
// Here argument of 'n' refers to maximum blocks that can be
// allocated which is guaranteed to be non-negative.
void *malloc(size_t n);
// While copying 'n' bytes from 's2' to 's1'
// n must be non-negative integer.
void *memcpy(void *s1, void const *s2, size_t n);
// the size of any string or `std::vector<char> st;` will always be at least 0.
size_t strlen(char const *s);
Size_t或任何无符号类型可能被视为循环变量,因为循环变量通常大于或等于0。
Size_t是unsigned int。所以当你需要unsigned int时,你可以使用它。
我使用它当我想指定数组的大小,计数器等…
void * operator new (size_t size); is a good use of it.
Size_t是sizeof操作符的结果类型。
size_t用于对数组的大小或索引进行建模的变量。Size_t传达语义:您立即知道它表示字节或索引的大小,而不仅仅是另一个整数。
此外,使用size_t表示字节大小有助于使代码可移植。
简短的回答:
几乎没有。使用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,而是使用自己的实现。
当使用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;
}
不管x的值是多少,if表达式都会得到false。 我花了几天时间才意识到这一点(代码太简单了,我没有做单元测试),尽管只花了几分钟就找到了问题的根源。不确定是执行强制转换还是使用零更好。
if ((int)(i-x) > -1 or (i-x) >= 0)
两种方法都有效。这是我的测试
size_t i = 5;
cerr << "i-7=" << i-7 << " (int)(i-7)=" << (int)(i-7) << endl;
输出:i-7=18446744073709551614 (int)(i-7)=-2
我想听听其他人的意见。