用无符号循环variables反向迭代

我一直在和同事讨论如何使用size_t。 已经出现的一个问题是循环递减循环variables,直到达到零。

考虑下面的代码:

for (size_t i = n-1; i >= 0; --i) { ... } 

这会由于无符号整数环绕而导致无限循环。 你在这种情况下做什么? 写上面的代码似乎很容易,而且没有意识到你犯了一个错误。

我们团队的两个build议是使用以下样式之一:

 for (size_t i = n-1; i != -1 ; --i) { ... } for (size_t i = n; i-- > 0 ; ) { ... } 

但我不知道还有其他的select…

我个人喜欢:

 for (size_t i = n; i --> 0 ;) 

它有a)没有滑稽的-1 ,b)条件检查是助记符,c)以一个合适的笑脸结束。

无符号整数保证很好地包装。 他们只是执行算术模2 N。 所以一个容易阅读的习惯是这样的:

 for (size_t i = n-1; i < n ; --i) { ... } 

这将variables设置为您想要的初始值,显示迭代的意义(向下),并精确地给出您要处理的值的条件。

  1. 用algorithmreplace循环。
  2. 使用反向迭代器而不是整数。
  3. 从n到1倒数,但在循环内使用i-1而不是i

如果你担心不小心编写了这样的循环,一些编译器会警告这样的事情。 例如,gcc有一个由-Wtype-limits选项启用的警告(也由-Wextra启用):

 xc:42: warning: comparison of unsigned expression >= 0 is always true 

你在使用标准库容器吗? 如果是的话,我喜欢reverse_iterator

  vector<int> ivect; // push, push, push... vector<int>::reverse_iterator riter; for(riter=riter.rbegin(); riter!=ivect.rend(); ++riter) { //... } 

对于一个原始数组,你可以使用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 

非连续的对象迭代可以通过将对象指针存储在容器或数组中来完成:

 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 

如果你真的想使用一个裸体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 

i != -1依靠-1被默默地投给了size_t ,这对我来说似乎很脆弱,所以,在你select的选项中,我肯定会用后一个。 另一种可能性(尤其是如果你实际上并不需要i在循环体中,而只需要以相反的顺序迭代数组),将数组包装在std:: -like容器中,并在包装​​器上使用迭代器,使用rbeginrend方法。 例如, Boost.Array将支持后者的select。

这里是一个关于这个主题的良好讨论的指针。

我会尝试:

 for( size_t i = n; i != 0; i-- ) { // do stuff with array[ i - 1 ] } 
 size_t i = n-1; do { ... } while ( i-- != 0); 

如果需要,你可以用if (n > 0)来包装它。

另一种方式(无签名/无签名比较):

 for (size_t i = n-1; i + 1 > 0; i--) 

以来

 (i + 1 > 0) === (i > -1)