Yada
Yada

Reputation: 31235

C++ Declaring int in the for loop

Haven't used C++ in a while. I've been depending on my Java compiler to do optimization.

What's is the most optimized way to do a for loop in C++? Or it is all the same now with moderm compilers? In the 'old days' there was a difference.

for (int i=1; i<=100; i++)

OR

int i;
for (i=1; i<=100; i++)

OR

int i = 1;
for ( ; i<=100; i++)

Is it the same in C?

EDIT: Okay, so the overwhelming consensus is to use the first case and let the complier optimize with it if it want to.

Upvotes: 12

Views: 16308

Answers (10)

Max Power
Max Power

Reputation: 101

A c++ for loop is literally a packaged while loop.

for (int i=1; i<=100; i++)
{
    some foobar ; 
}

To the compiler, the above code is exactly the same as the code below.

{ 
int i=1 ;
    while (i<=100){
        some foobar ;
        i++ ; 
    }
}

Note the int i=1 ; is contained within a dedicated scope that encloses only it and the while loop.

Upvotes: 0

TommyGunn32
TommyGunn32

Reputation: 934

for(int i = 1; i <= 100; ++i)

This is easiest to read, except for ANSI C / C89 where it is invalid.

Upvotes: 1

Jesse K
Jesse K

Reputation: 136

Let's say the original poster had a loop they really wanted optimized - every instruction counted. How can we figure out - empirically - the answer to his question?

gcc at least has a useful, if uncommonly used switch, '-S'. It dumps the assembly code version of the .c file and can be used to answer questions like the OP poses. I wrote a simple program:

int main( )
{
    int sum = 0;

    for(int i=1;i<=10;++i)
    {
        sum = sum + i;
    }
    return sum;
}

And ran: gcc -O0 -std=c99 -S main.c, creating the assembly version of the main program. Here's the contents of main.s (with some of the fluff removed):

    movl    $0, -8(%rbp)
    movl    $1, -4(%rbp)
    jmp     .L2
.L3:
    movl    -4(%rbp), %eax
    addl    %eax, -8(%rbp)
    addl    $1, -4(%rbp)
.L2:
    cmpl    $10, -4(%rbp)
    jle     .L3

You don't need to be an assembly expert to figure out what's going on. movl moves values, addl adds things, cmpl compares and jle stands for 'jump if less than', $ is for constants. It's loading 0 into something - that must be 'sum', 1 into something else - ah, 'i'! A jump to L2 where we do the compare to 10, jump to L3 to do the add. Fall through to L2 for the compare again. Neat! A for loop.

Change the program to:

int main( )
{
    int sum = 0;
    int i=1;
    for( ;i<=10;++i)
    {
        sum = sum + i;
    }
    return sum;
}

Rerun gcc and the resultant assembly will be very similar. There's some stuff going on with recording line numbers, so they won't be identical, but the assembly ends up being the same. Same result with the last case. So, even without optimization, the code's just about the same.

For fun, rerun gcc with '-O3' instead of '-O0' to enable optimization and look at the .s file.

main:
movl    $55, %eax
ret

gcc not only figured out we were doing a for loop, but also realized it was to be run a constant number of times did the loop for us at compile time, chucked out 'i' and 'sum' and hard coded the answer - 55! That's FAST - albeit a bit contrived.

Moral of the story? Spend your time on ensuring your code is clean and well designed. Code for readability and maintainability. The guys that live on mountain dew and cheetos are way smarter than us and have taken care of most of these simple optimization problems for us. Have fun!

Upvotes: 8

Jeff Barger
Jeff Barger

Reputation: 1239

It has already been mentioned that the main difference between the two is scope. Make sure you understand how your compiler handles the scope of an int declared as

for (int i = 1; ...;...)

I know that when using MSVC++6, i is still in scope outside the loop, just as if it were declared before the loop. This behavior is different from VS2005, and I'd have to check, but I think the last version of gcc that I used. In both of those compilers, that variable was only in scope inside the loop.

Upvotes: 1

Javier
Javier

Reputation: 4623

I'd say that trivial things like this are probably optimized by the compiler, and you shouldn't worry about them. The first option is the most readable, so you should use that.

EDIT: Adding what other answers said, there is also the difference that if you declare the variable in the loop initializer, it will stop to exist after the loop ends.

Upvotes: 12

Mark Byers
Mark Byers

Reputation: 838974

It's the same. The compiler will optimize these to the same thing.

Even if they weren't the same, the difference compared to the actual body of your loop would be negligible. You shouldn't worry about micro-optimizations like this. And you shouldn't make micro-optimizations unless you are performance profiling to see if it actually makes a difference.

Upvotes: 4

rmn
rmn

Reputation: 2426

It's all the same.

Upvotes: -1

outis
outis

Reputation: 77440

Don't worry about micro-optimizations, let the compiler do it. Pick whichever is most readable. Note that declaring a variable within a for initialization statement scopes the variable to the for statement (C++03 § 6.5.3 1), though the exact behavior of compilers may vary (some let you pick). If code outside the loop uses the variable, declare it outside the loop. If the variable is truly local to the loop, declare it in the initializer.

Upvotes: 2

Jonathan M Davis
Jonathan M Davis

Reputation: 38287

The difference is scope.

for(int i = 1; i <= 100; ++i)

is generally preferable because then the scope of i is restricted to the for loop. If you declare it before the for loop, then it continues to exist after the for loop has finished and could clash with other variables. If you're only using it in the for loop, there's no reason to let it exist longer than that.

Upvotes: 11

Uri
Uri

Reputation: 89829

It's the same in term of speed. Compiler will optimize if you do not have a later use of i.

In terms of style - I'd put the definition in the loop construct, as it reduces the risk that you'll conflict if you define another i later.

Upvotes: 3

Related Questions