nha*_*123 187 c++ types idiomatic size-t loop-counter
我只是想知道我应该使用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?
}
}Run Code Online (Sandbox Code Playgroud)
一般来说,何时使用的最佳做法是什么std::size_t?
CB *_*ley 172
一个好的经验法则是你需要在循环条件下比较自然的东西std::size_t.
std::size_t是任何sizeof表达式的类型,并且保证能够在C++中表达任何对象(包括任何数组)的最大大小.通过扩展,它也保证足够大,可以用于任何数组索引,因此它是一个循环索引的自然类型.
如果你只计算一个数字,那么使用保存该数字的变量的类型或者int或者unsigned int(如果足够大)可能更自然,因为这些应该是机器的自然大小.
Gre*_*osz 70
size_t是sizeof运算符的结果类型.
使用size_t变量数组中的模型的大小或指数.size_t传达语义:你立即知道它代表一个字节大小或索引,而不只是另一个整数.
此外,size_t用于表示字节大小有助于使代码可移植.
pax*_*blo 31
该size_t类型用于指定某些内容的大小,因此使用它是很自然的,例如,获取字符串的长度然后处理每个字符:
for (size_t i = 0, max = strlen (str); i < max; i++)
doSomethingWith (str[i]);
Run Code Online (Sandbox Code Playgroud)
你也必须注意,当然边界条件,因为它是一个无符号类型.因为最大通常比较大(虽然它在高端产品的界限通常不是重要的是可以到那里).大多数人只是使用一种int东西,因为他们很少有足够大的结构或阵列来超过容量int.
但请注意以下事项:
for (size_t i = strlen (str) - 1; i >= 0; i--)
Run Code Online (Sandbox Code Playgroud)
由于无符号值的包装行为,这将导致无限循环(虽然我看到编译器警告这一点).这也可以通过(稍微难以理解,但至少不受包装问题影响)来缓解:
for (size_t i = strlen (str); i-- > 0; )
Run Code Online (Sandbox Code Playgroud)
通过将递减转换为连续条件的后检查副作用,这将在递减之前检查值的继续,但仍然使用循环内的递减值(这是循环运行len .. 1而不是len-1 .. 0)的原因.
小智 10
size_t是一种非常易读的方式来指定项目的大小维度 - 字符串的长度,指针占用的字节数等等.它也可以跨平台移植 - 你会发现64位和32位都能很好地处理系统功能和size_t-东西,unsigned int什么时候应该使用也许不会那么做(如unsigned long
使用std :: size_t索引/计数C样式数组.
对于STL容器,您将拥有(例如)vector<int>::size_type,它应该用于索引和计算向量元素.
实际上,它们通常都是无符号整数,但不能保证,特别是在使用自定义分配器时.
很快,大多数计算机将采用64位操作系统的64位架构:运行在数十亿元素容器上运行的程序.然后,你必须使用size_t,而不是int作为循环索引,否则你的索引将环绕在2 ^ 32:th元素,在32位和64位系统.
为未来做好准备!
几乎从不
每当你需要在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]);
Run Code Online (Sandbox Code Playgroud)
签名的等价物size_t是ptrdiff_t,不是int.但int在大多数情况下,使用仍然比size_t好得多.ptrdiff_t是long在32个64位系统.
这意味着每当你与std :: containers进行交互时,你总是必须与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)]);
Run Code Online (Sandbox Code Playgroud)
如果只是想迭代一个集合,没有边界检查,使用范围基于:
for(const auto& d : data) {
[...]
}
Run Code Online (Sandbox Code Playgroud)
这里有来自Bjarne Stroustrup(C++作者)的一些关于本土的话
对于某些人来说,STL中这个签名/未签名的设计错误是合理的,不使用std :: vector,而是使用自己的实现.
小智 6
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");
}
Run Code Online (Sandbox Code Playgroud)
使用无符号整数有可能产生这些类型的微妙问题。因此,恕我直言,我更喜欢仅在与需要它的容器/类型交互时才使用 size_t 。
| 归档时间: |
|
| 查看次数: |
93008 次 |
| 最近记录: |