A good compiler--or at least one with optimization turned on--would probably do the latter.
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;-).
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 :)
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.
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 */) {
}
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.