【问题标题】:In a "for" statement, should I use `!=` or `<`?在“for”语句中,我应该使用 `!=` 还是 `<`?
【发布时间】:2011-12-31 23:36:09
【问题描述】:

这两个for语句我都见过:

for(i=0;i<10;i++) 

for(i=0;i!=10;i++)

我知道当我到达 10 时它们都会停止,但使用第二个似乎更好(我听说)。 有什么不同?我也想知道什么时候使用迭代器访问向量的成员,迭代器条件&lt; vec.end()!= vec.end()有什么区别

【问题讨论】:

  • 只是为了说明,在 for 循环中,++i 优于 i++,因为第二个存储了 i 的前一个值,而第一个没有。
  • @PaulManta:我认为大多数现代编译器都能够找出未使用的中间值并将其优化掉。
  • @BrendanLong:对于原始类型,它可以。对于迭代器,++i至少 一样快,也许更快。
  • @arne 是的,现代编译器通常会这样做......但是“通常”部分让我感到困惑。 :) 总是把它写成++i 并且不依赖编译器来优化它并不像我花费任何代价。
  • @PaulManta:那是完全不同的故事;)我通常也写++i,这样我的代码看起来都是一样的,不管i是什么类型。

标签: c++ loops for-loop conditional-statements


【解决方案1】:

两者都适用于大多数情况。

如果由于某种原因循环中执行的代码主体将i 更改为大于10,第一个版本将停止循环,但第二个版本将永远执行。

【讨论】:

    【解决方案2】:
    for(i = start; i != end; ++i)
    

    这是“标准”迭代器循环。它的优点是它可以与指针和标准库迭代器一起使用(你不能依赖定义了operator&lt; 的迭代器)。

    for(i = start; i < end; ++i)
    

    这不适用于标准库迭代器(除非它们定义了operator&lt;),但它确实有一个优点,即如果您出于某种原因超过end,它仍然会停止,因此它会稍微安全一些。我被教导在迭代整数时使用它,但我不知道它是否真的被认为是“最佳实践”。

    我一般写这些的方式是更喜欢&lt;

    【讨论】:

    • 实际上,对于指针/迭代器,只有在迭代部分范围时才更安全。如果end 代表范围的结束,那么超过end未定义的行为,因此无论条件如何,所有赌注都关闭。
    • 同意——它更安全的想法有点简单化。如果你的循环没有做你认为它正在做的事情,那是不安全的。不过,我试图将我听到的“最佳实践”呈现出来。
    • 假设有人决定通过将循环变量设置为结束值来终止循环,而不是出于某种原因调用 break。然后你增加整数并比较它不相等......我认为第二种形式的范围更小,有人不小心把它搞砸了。
    • @Matthieu M. - 是的,越过结尾是未定义的行为,但这并非不可能。如果超过末尾,您是否更愿意使用 != 并抛出异常?
    • @NathanLong:我的观点是,如果您调用未定义的行为,那么无论您使用 != 还是 &lt; 都无关紧要,因为未定义行为的本质是任何事情都可能发生(众所周知恶魔飞出你的节点)。
    【解决方案3】:
    如果 i 的值超过 10,

    != 将允许测试评估为真,而如果 i 超过 10 或仅等于它,

    如果 i 的值可能在循环体中发生变化,这可能是一个考虑因素。

    但是,如果您只是想多次执行某项操作,则

    【讨论】:

      【解决方案4】:

      我知道当我达到 10 时它们都会停止,但使用起来似乎更好 第二个(我听说过)。

      这是一个微优化。使用任何更有意义的东西(&lt; 以上更有意义)。

      有什么不同?

      第一个版本使用不等号运算符!=,第二个版本使用小于号运算符&lt;

      【讨论】:

      • 另外,第二个选项假定你永远不会在循环体中增加 i 。如果您碰巧这样做,您可能会陷入无限循环。我个人同意@VJo 并认为代码应该首先表达其意图。所以对我来说真正的问题是你是想循环直到 i 是 10 还是当 i 不是 10 时?
      【解决方案5】:

      for ( initialization ; termination condition ; iteration )

      对于每一个,选择最适合您要求的,对于termination condition,您可以使用任何二元条件运算符,例如&gt;,&lt;,&gt;=,&lt;=,@ 987654327@

      对于你给定的问题,考虑一个随机的情况,

      for(i=0;i!=10;i++)
      {
       .
       .
       i=11; //somewhere if the loop variable is changed to a value greater than 10 (this assumption is solely for demo)
       .
       .
       .
      }
      

      在这种情况下,循环结果是无限的。相反,如果您使用条件i&lt;10,这将照常工作。所以我的观点是,第一种方法严格设置条件更安全。

      【讨论】:

      • 假设将i 设置为 11 不是有意会产生一个无限循环(或者无论如何会一直持续到将其设置为 9),在这种情况下你会使用i != 10。就我个人而言,我认为不值得尝试对破坏你自己的循环不变量的人进行防御性编码——要么循环体应该修改i(在这种情况下,你编写的代码有点粗糙,无论如何都必须小心终止条件是),或者它不应该是(在这种情况下,我不会费心尝试默默地处理一个循环体,因为它无论如何都是错误的)。
      • @Steve 提出了一个很好的观点。如果你担心有人在你的代码中设置 i=11 所以你使用 i
      【解决方案6】:

      我的日常习惯是在使用简单类型(例如整数)迭代循环时使用 &lt;,在使用 stl 类迭代器时使用 !=

      【讨论】:

      • 谢谢!我以前认为所有的迭代器都有一个&lt; 运算符。我是多么愚蠢!
      • 您的评论位置错误。我想,你想对@BrendanLong 说。
      • 我们应该so请求template&lt;typename Iter&gt; std::iterator_comparison_traits&lt;Iter&gt;,其成员typedef的计算结果分别为std::less&lt;Iter&gt;std::not_equal_to&lt;Iter&gt;
      【解决方案7】:

      最佳实践是 != 仅与迭代器 (C++) 一起使用,否则使用

      for (double i = 0.0; i != 1.0; i += 0.1)
          printf("yes, I'm an infinite loop ;)");
      

      【讨论】:

        【解决方案8】:

        出于其他人所述的原因,我通常在 for 循环中使用 &lt;。不过,在 while 循环和更高级的 for 循环中,!= 可以更轻松地推断我的程序做了什么。

        假设我想在 [5,5,5,3,5,2,3,2,0] 这样的数组中找到第一次运行 '5' 后的位置。那就是我们想要k 这样0 &lt;= i &lt; k =&gt; a[i] = 5

        int pos = 0;
        // Inv: a[0..pos) = 5
        while (pos != N && a[pos] == 5)
            pos = pos+1;
        

        一旦循环执行完毕,我们就知道循环保护的逆函数为真:pos == N || a[pos] != 5。无论哪种情况,我们都有我们想要的pos

        现在假设我们在循环保护中使用了&lt;,那么之后我们只知道pos &gt;= N || a[pos] != 5,但这不是我们想要的情况。做更多的工作,我们可以证明我们不可能在 pos &gt; N 中,但与仅在循环保护中使用 != 相比,这似乎是在浪费时间。

        【讨论】:

          猜你喜欢
          • 2021-02-03
          • 2020-11-02
          • 1970-01-01
          • 1970-01-01
          • 2013-03-25
          • 2012-02-15
          • 1970-01-01
          • 2016-12-28
          • 2011-11-29
          相关资源
          最近更新 更多