我一直在讨论与同事一起使用size_t的问题.出现的一个问题是循环,它将循环变量递减直到达到零.
请考虑以下代码:
for (size_t i = n-1; i >= 0; --i) { ... }
Run Code Online (Sandbox Code Playgroud)
由于无符号整数环绕,这会导致无限循环.在这种情况下你做什么?编写上面的代码并没有意识到你犯了一个错误似乎很容易.
我们团队的两个建议是使用以下样式之一:
for (size_t i = n-1; i != -1 ; --i) { ... }
for (size_t i = n; i-- > 0 ; ) { ... }
Run Code Online (Sandbox Code Playgroud)
但我不知道还有其他选择......
vis*_*tor 84
就个人而言,我喜欢:
for (size_t i = n; i --> 0 ;)
Run Code Online (Sandbox Code Playgroud)
它有a)没有趣-1,b)条件检查是助记符,c)它以适当的笑脸结束.
Jen*_*edt 55
无符号整数保证很好地包裹.他们只是执行算术模2 ñ.所以这个易于阅读的习语是这样的:
for (size_t i = n-1; i < n ; --i) { ... }
Run Code Online (Sandbox Code Playgroud)
这会将变量设置为您想要的初始值,显示迭代的意义(向下)并精确地给出您要处理的值的条件.
您使用的是标准库容器吗?如果是这样我喜欢reverse_iterator
vector<int> ivect;
// push, push, push...
vector<int>::reverse_iterator riter;
for(riter=riter.rbegin(); riter!=ivect.rend(); ++riter)
{
//...
}
Run Code Online (Sandbox Code Playgroud)
对于原始数组,您只需使用std::reverse_iterator键即指针是迭代器:
int i[] = {1, 2, 3, 4};
typedef std::reverse_iterator<const int*> irevit;
irevit iter(i+4);
irevit end(i);
for(; iter != end; ++iter) {
cout << *iter;
}
// Prints 4321
Run Code Online (Sandbox Code Playgroud)
可以通过将对象指针存储在容器或数组中来完成非连续对象迭代:
struct Foo {
Foo(int i) I(i) { }
int I;
}
vector<Foo*> foos;
for(int i = 0; i < 10; ++i)
foos.push_back(new Foo(i));
typedef vector<Foo*>::const_reverse_iterator frevit;
frevit iter(foos.rbegin());
for(; iter != foos.rend(); ++iter) {
cout << (*iter)->I;
}
// Prints 9876543210
Run Code Online (Sandbox Code Playgroud)
如果你真的想要裸体使用size_t那么为什么在其他答案中使用所有这些隐含的混乱-1欺骗?最大值size_t明确可用作终止值:
int is[] = {1, 2, 3, 4};
int n = 3;
for (size_t i = n; i != std::numeric_limits<size_t>::max(); --i) {
cout << is[i] << endl;
}
// prints 4321
Run Code Online (Sandbox Code Playgroud)
如果你担心意外写这样的循环,一些编译器会警告这些事情.例如,gcc通过-Wtype-limits选项启用警告(也启用-Wextra):
x.c:42: warning: comparison of unsigned expression >= 0 is always true
Run Code Online (Sandbox Code Playgroud)
从 C++20 开始,您可以使用范围和视图,如下所示:
namespace sv = std::views;
for (unsigned i : sv::iota(0u, n) | sv::reverse)
std::cout << i << "\n";
Run Code Online (Sandbox Code Playgroud)
这是一个演示。
该代码非常可读,并且它完全避免了无符号环绕行为的任何问题,因为i只有范围内的值[0,n)。
| 归档时间: |
|
| 查看次数: |
11920 次 |
| 最近记录: |