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

后端 未结 21 2102
小蘑菇
小蘑菇 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.

提交回复
热议问题