views:

437

answers:

6
+1  A: 

A good compiler--or at least one with optimization turned on--would probably do the latter.

Dr. Watson
+6  A: 

They take up exactly the same amount of memory -- sizeof(int) bytes; the first one doesn't make y visible outside the braces, the second one does. No waste in either case (assuming in both cases that more code follows before the } of course;-).

Alex Martelli
I mean isn't y redefining itself in new memory location or does it defines in the same memory location?
Y_Y
If y is redefining itself in new memory is the old memory place erased or free to used again?
Y_Y
The compiler allocates stack variables by deepening the stack. This amounts to changing one register that keeps track of how deep where the stack ends. So the question then is: does the compiler generate code that pushes and pops the stack each time through the loop? The answer is most likely to be no. The compiler will write code that allocates space on the stack for the variable and use that same space throughout the entire function at runtime. There are more side effects if the variable represents an object because it will be created and destroyed, possibly requiring heap [de]allocations.
hughdbrown
wow cool... make sence
Y_Y
@hughdbrown has it just right, and if y'all ever had to study the resulting machine code (as we all used to do back when C++ compilers were flaky...;-) that would be obvious!-)
Alex Martelli
+1  A: 

Doesn't really matter with the modern day compilers. Code will (in most cases) be optimized into the 2nd sample. And even if it doesn't, it's a single push to the stack every time y is declared (in the first example) and pop when the 'for' brace is ended so it's not a waste of memory though it can be waste of some CPU cycles. But we have lots of those available nowadays anyway :)

Aamir
Yeah this make sence...!
Y_Y
A: 

They are equivalent both in terms of function and memory usage.

If there is more code in the function after the loops, the latter may occupy more stack space for the duration of the remainder of that function call (sizeof(int) bytes), depending on what other local variables are defined and the compiler optimization settings.

But for all intents and purposes, the two are identical to the point where it is irrelevant which you choose; pick the one that best suits your coding guidelines/standards/taste.

Wez Furlong
+19  A: 

Memory-wise, there is no difference. y is on the stack, wherever it's declared within the method. Here the only difference is the scope of y: in the second case, it is restricted to the body of the for loop; in the first, it isn't. This is purely at the language-level: again, y is allocated in exactly the same way, that is, on the stack.

Just to make this point perfectly clear, here's a code example:

void method1() {
    for (;;) {
     int a = 10;
    }
}

void method2() {
    int a;
    for (;;) {
     a = 10;
    }
}

Here is the assembler generated in debug mode in both cases :

# method1() 
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  cmp         dword ptr ds:[00662E14h],0 
0000000b  je          00000012 
0000000d  call        5D9FE081 
00000012  xor         edx,edx 
00000014  mov         dword ptr [ebp-4],edx 
00000017  mov         dword ptr [ebp-4],0Ah 
0000001e  nop              
0000001f  jmp         00000017 

# method2() 
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  cmp         dword ptr ds:[002B2E14h],0 
0000000b  je          00000012 
0000000d  call        5ED1E089 
00000012  xor         edx,edx 
00000014  mov         dword ptr [ebp-4],edx 
00000017  mov         dword ptr [ebp-4],0Ah 
0000001e  nop              
0000001f  jmp         00000017

Even without knowing anything about assembly, you can see that both methods have exactly the same instructions. In other words, at the point where a is declared, nothing happens.

There is an important difference however if you are using any type that has a constructor, say, an std::vector: at the point where it is declared, the constructor is called, so if you declare it within a loop, it will be reconstructed each time through the loop. For example:

for (/* index */) {
    std::vector<int> a; // invokes the constructor of std::vector<int> everytime
} // destructor called each time the object goes out of scope

std::vector<int> a; // constructor only called once
for (/* index */) {

}

The situation gets worse if you are using new: these two pieces of code behave very differently:

for (/* index */) {
    char *a = new char[100]; // allocates 100 additional bytes every time !
} // must remember to delete[] a in the loop, otherwise it's a memory leak !

//////

char *a = new char[100]; // only one allocation
for (/* index */) {

}
Dr_Asik
Ohh so only when calling a constructor the variable will be reconstructed...
Y_Y
oh yeah that make sense cause in the first case each time the loops goes a new instance of a is declared... I am just a little confuse on whether the variable y is store in the same memory space or is it store in a new location? if the second is true then what's with the old memory location?
Y_Y
In the case of int, the declaration does nothing. You can view it as if y was declared at the top of the method, but only visible inside the loop. What you need to understand is that declaring something statically does not cause a memory allocation at the point of declaration. It only causes the stack pointer to be incremented a bit more when the method is called. When you learn some assembly this will hopefully become clearer.
Dr_Asik
thanks for the assembly code!
Y_Y
A: 

One important difference as written: if you do

for(int x=0;x<100;x++)
{
  int y = 1+x;
}
z = y-3; // <=== ERROR!

you can not access y outside of the for loop.

While when you use

int y = 0;
for(int x=0;x<100;x++)
{
  y = 1+x;
}
z = y-3; // <=== OK

y continues to be visible to you lower in the enclosing scope.

dmckee
yeah true... scope wise the second make sence. I just wanted to know how the computer acted between the 2.
Y_Y
@Y_Y: I suspected you did, but figured that the poit should be made, because the quetion title might attract some real beginners.
dmckee