Technical reasons behind formatting when increment

2020-01-27 02:02发布

All over the web, code samples have for loops which look like this:

for(int i = 0; i < 5; i++)

while I used the following format:

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

I do this because I believe it to be more efficient, but does this really matter in most cases?

30条回答
狗以群分
2楼-- · 2020-01-27 02:42

I would never do this:

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

i != 5 leaves it open for the possibility that i will never be 5. It's too easy to skip over it and run into either an infinite loop or an array accessor error.

++i

Although a lot of people know that you can put ++ in front, there are a lot of people who don't. Code needs to be readable to people, and although it could be a micro optimization to make the code go faster, it really isn't worth the extra headache when someone has to modify the code and figure why it was done.

I think Douglas Crockford has the best suggestion and that is to not use ++ or -- at all. It can just become too confusing (may be not in a loop but definitely other places) at times and it is just as easy to write i = i + 1. He thinks it's just a bad habit to get out of, and I kind of agree after seeing some atrocious "optimized" code.

I think what crockford is getting at is with those operators you can get people writing things like:

var x = 0;
var y = x++;

y = ++x * (Math.pow(++y, 2) * 3) * ++x;

alert(x * y);

//the answer is 54 btw.

查看更多
对你真心纯属浪费
3楼-- · 2020-01-27 02:42

To sum up pros and cons of both options

Pros of !=

  • when int is replaced with some iterator or a type passed via template argument there is better chance it will work, it will do what is expected and it will be more efficient.
  • will 'loop forever' if something unpredicted happens to the i variable allowing bug detection

Pros of <

  • as other say is as efficient as the other one with simple types
  • it will not run 'forever' if i is increased in the loop or 5 is replaced with some expression that gets modified while the loop is running
  • will work with float type
  • more readable - matter of getting used to

My conclusions:

  1. Perhaps the != version should be used in majority of cases, when i is discrete and it is as well as the other side of the comparison is not intended to be tampered within the loop.

  2. While the presence of < would be a clear sign that the i is of simple type (or evaluates to simple type) and the condition is not straightforward: i or condition is additionally modified within the loop and/or parallel processing.

查看更多
Bombasti
4楼-- · 2020-01-27 02:43

It is not good approach to use as != 5. But

for (int i =0; i<index; ++i)

is more efficient than

for(int i=0; i<index; i++)

Because i++ first perform copy operation. For detailed information you can look operator overloading in C++.

查看更多
混吃等死
5楼-- · 2020-01-27 02:44

If for some reason i jumps to 50 in the loop, your version would loop forever. The i < 5 is a sanity check.

查看更多
甜甜的少女心
6楼-- · 2020-01-27 02:44

It appears no one has stated the reason why historically the preincrement operator, ++i, has been preferred over the postfix i++, for small loops.

Consider a typical implementation of the prefix (increment and fetch) and the postfix (fetch and increment):

// prefix form: increment and fetch
UPInt& UPInt::operator++()
{
   *this += 1;      // increment
   return *this;    // fetch
}

// posfix form: fetch and increment
const UPInt UPInt::operator++(int)
{
   const UPInt oldValue = *this;
   ++(*this);
   return oldValue;
} 

Note that the prefix operation can be done in-place, where as the postfix requires another variable to keep track of the old value. If you are not sure why this is so, consider the following:

int a = 0;
int b = a++; // b = 0, the old value, a = 1 

In a small loop, this extra allocation required by the postfix could theoretically make it slower and so the old school logic is the prefix is more efficient. As such, many C/C++ programmers have stuck with the habit of using the prefix form.

However, noted elsewhere is the fact that modern compilers are smart. They notice that when using the postfix form in a for loop, the return value of the postfix is not needed. As such, it's not necessary to keep track of the old value and it can be optimized out - leaving the same machine code you would get from using the prefix form.

查看更多
祖国的老花朵
7楼-- · 2020-01-27 02:45

It is not a good idea to care about efficiency in those cases, because your compiler is usually smart enough to optimize your code when it is able to.

I have worked to a company that produces software for safety-critical systems, and one of the rules was that the loop should end with a "<" instead of a !=. There are several good reasons for that:

  1. Your control variable might jump to a higher value by some hw problem or some memory invasion;

  2. In the maintenance, one could increment your iterator value inside the loop, or do something like "i += 2", and this would make your loop to roll forever;

  3. If for some reason your iterator type changes from "int" to "float" (I don't know why someone would do that, but anyways...) an exact comparison for float points is a bad practice.

(The MISRA C++ Coding Standard (for safety-critical systems) also tell you to prefer the "<" instead of "!=" in the rule 6-5-2. I don't know if I can post the rule definition here because MISRA is a paid document.)

About the ++i or i++, I'd preffer to use ++i. There is no difference for that when you are working with basic types, but when you are using a STL iterator, the preincrement is more efficient. So I always use preincrement to get used to it.

查看更多
登录 后发表回答