Is there a technical reason to use > (<) instead of != when incrementing by 1 in a 'for' loop?

后端 未结 21 2006
小蘑菇
小蘑菇 2020-12-23 19:48

I almost never see a for loop like this:

for (int i = 0; 5 != i; ++i)
{}

Is there a technical reason to use >

相关标签:
21条回答
  • 2020-12-23 20:35

    The most common reason to use < is convention. More programmers think of loops like this as "while the index is in range" rather than "until the index reaches the end." There's value is sticking to convention when you can.

    On the other hand, many answers here are claiming that using the < form helps avoid bugs. I'd argue that in many cases this just helps hide bugs. If the loop index is supposed to reach the end value, and, instead, it actually goes beyond it, then there's something happening you didn't expect which may cause a malfunction (or be a side effect of another bug). The < will likely delay discovery of the bug. The != is more likely to lead to a stall, hang, or even a crash, which will help you spot the bug sooner. The sooner a bug is found, the cheaper it is to fix.

    Note that this convention is peculiar to array and vector indexing. When traversing nearly any other type of data structure, you'd use an iterator (or pointer) and check directly for an end value. In those cases you have to be sure the iterator will reach and not overshoot the actual end value.

    For example, if you're stepping through a plain C string, it's generally more common to write:

    for (char *p = foo; *p != '\0'; ++p) {
      // do something with *p
    }
    

    than

    int length = strlen(foo);
    for (int i = 0; i < length; ++i) {
      // do something with foo[i]
    }
    

    For one thing, if the string is very long, the second form will be slower because the strlen is another pass through the string.

    With a C++ std::string, you'd use a range-based for loop, a standard algorithm, or iterators, even if though the length is readily available. If you're using iterators, the convention is to use != rather than <, as in:

    for (auto it = foo.begin(); it != foo.end(); ++it) { ... }
    

    Similarly, iterating a tree or a list or a deque usually involves watching for a null pointer or other sentinel rather than checking if an index remains within a range.

    0 讨论(0)
  • 2020-12-23 20:39

    One reason not to use this construct is floating point numbers. != is a very dangerous comparison to use with floats as it'll rarely evaluate to true even if the numbers look the same. < or > removes this risk.

    0 讨论(0)
  • 2020-12-23 20:40

    You can have something like

    for(int i = 0; i<5; ++i){
        ...
        if(...) i++;
        ...
    }
    

    If your loop variable is written by the inner code, the i!=5 might not break that loop. This is safer to check for inequality.

    Edit about readability. The inequality form is way more frequently used. Therefore, this is very fast to read as there is nothing special to understand (brain load is reduced because the task is common). So it's cool for the readers to make use of these habits.

    0 讨论(0)
  • 2020-12-23 20:43

    As already said by Ian Newson, you can't reliably loop over a floating variable and exit with !=. For instance,

    for (double x=0; x!=1; x+=0.1) {}
    

    will actually loop forever, because 0.1 can't exactly be represented in floating point, hence the counter narrowly misses 1. With < it terminates.

    (Note however that it's basically undefined behaviour whether you get 0.9999... as the last accepted number – which kind of violates the less-than assumption – or already exit at 1.0000000000000001.)

    0 讨论(0)
  • 2020-12-23 20:47

    There is no technical reason. But there is mitigation of risk, maintainability and better understanding of code.

    < or > are stronger restrictions than != and fulfill the exact same purpose in most cases (I'd even say in all practical cases).

    There is duplicate question here; and one interesting answer.

    0 讨论(0)
  • 2020-12-23 20:47

    I would argue that an expression like

    for ( int i = 0 ; i < 100 ; ++i )
    {
      ...
    }
    

    is more expressive of intent than is

    for ( int i = 0 ; i != 100 ; ++i )
    {
      ...
    }
    

    The former clearly calls out that the condition is a test for an exclusive upper bound on a range; the latter is a binary test of an exit condition. And if the body of the loop is non-trivial, it may not apparent that the index is only modified in the for statement itself.

    0 讨论(0)
提交回复
热议问题