position of automatic variables declaration wrt loops

In some code I'm looking over, I'm seeing a fair bit of this sort of thing :

1.
1
2
3
4
5
Type *ptr;
for( int i=0; i<count(); ++i ) {
  ptr = new Type;
  dosomethingwithptr( ptr );
}


clearly ptr has more scope than needed. The alternatives are putting it inside the loop :

2.
1
2
3
4
for( int i=0; i<count(); ++i ) {
  Type *ptr = new Type;
  dosomethingwithptr( ptr );
}


or in the for construct :

3.
1
2
3
4
for( int i=0, Type *ptr; i<count(); ++i ) {
   ptr = new Type;
   dosomethingwithptr( ptr );
}


My preference is 2, but it clearly requires a ptr to be pushed on the stack and popped off again every iteration.
The ideal is 3., but it looks odd, and isn't so easy to read, especially with many variables.

Perhaps surrounding the whole lot in an anonymous block :

1
2
3
4
5
6
7
{
  Type *ptr;
  for( int i=0; i<count(); ++i ) {
    ptr = new Type;
    dosomethingwithptr( ptr );
  }
}


What are the arguments for and against each of these? Anything I've missed?
id go for

1
2
for(int i =  0; i < count(); i++)
    dosomethingwithptr(new Type);



but if i had to choose between 1 and 2, id go for 2, as arguement, readability, and that ptr wont be outside of the for loop
but i have no idea if one is better than another

3 seems the best, but, i never do it, just looks sortof strange
(id rather use 3 than 4 though)
Last edited on
My preference is 2, but it clearly requires a ptr to be pushed on the stack and popped off again every iteration.
This isn't the case. All that changes is the visibility of the variable, so it's ok to use your preferred method without a runtime penality.
I'd go with Skilless's solution above any of the others suggested, though none are exception safe.
davidmaxwaterman wrote:
My preference is 2, but it clearly requires a ptr to be pushed on the stack and popped off again every iteration.


There is no pushing and popping like that of local variables. Memory for local variables is
allocated at the start of the function on the stack. Compiler puts in code to call Constructors/Destructors at the start and end of the scope for variables as required.
At the end of the function the stack space is reclaimed.
Last edited on
Ah, interesting that there is no memory allocation done for each iteration in case 2. I assumed memory was allocated at the start of a '{' '}' block, and a function/method wasn't anything special in that respect.

Is this behaviour part of C++, or does it depend on which compiler you use?
They all do it like this.
@guestgulkan:
Memory for local variables is allocated at the start of the function on the stack


Just to observe the above ,I ran the below code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;

int main()
{
   for(int i = 0;i<2;i++)
  {
  int k;
  cout<<"   "<<&k;
  }
  for(int i = 0;i<2;i++)
  {
  int k;
  cout<<"   "<<&k;
  }
return 0;
}



Output is :
ffbffb34 ffbffb34 ffbffb2c ffbffb2c

Address of k is different in different loops.
But local variable k was allocated at the begining of main,its address should have been same throughout.
Going by this i guess the allocation happens at the start of a '{' '}' block.
If I am misinterpreting it,just let me know what am i missing.
The compiler has the opprotunity to reuse the space. Just because an implementation doesn't, as a given optimistation level, doesn't mean it can't or even that it won't at a different optimistation level.
@kbw :Can you please elaborate ..it went over my head. :o
Can you please elaborate

First, looking at what a particular compiler does in particular circumstances should be a guide to what the language says.

In your example above, your compiler has reserved seperate addresses for the two different k. I take it you compiled with optimisations off.

The compiler is free to reuse the space such that both instances of k use the same address. If the compiler is optimising for size, that would be a candidate for improvement and it may or may not use it. Maybe a future version or a different vendors compiler will.

The point is, you've made it clear that each instance of k is confined in scope. The compiler is free to use it. But if it doesn't, that doesn't make your code wrong.
Last edited on
@guestgulkan:
Memory for local variables is allocated at the start of the function on the stack


Just to observe the above ,I ran the below code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;

int main()
{
   for(int i = 0;i<2;i++)
  {
  int k;
  cout<<"   "<<&k;
  }
  for(int i = 0;i<2;i++)
  {
  int k;
  cout<<"   "<<&k;
  }
return 0;
}

Output is :
ffbffb34 ffbffb34 ffbffb2c ffbffb2c

Address of k is different in different loops.
But local variable k was allocated at the begining of main,its address should have been same throughout.
Going by this i guess the allocation happens at the start of a '{' '}' block.
If I am misinterpreting it,just let me know what am i missing.



You are misinterpreting.
You have two entirely seperate variables called k
They are in different scopes.
You also have two entirely differnt variables call i
Last edited on
FWIW, I compile and run that exact code on my Ubuntu Linux system with 'g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3' and I get this :

 
   0xbf8f04c4   0xbf8f04c4   0xbf8f04c4   0xbf8f04c4


I get the same even if I use -O0 (but I see from the manual that it is the default). I see no way to get less optimisation that than.

I wonder why a compiler would *not* use the same address for the two variables? It seems so obvious that I would expect that behaviour.
Topic archived. No new replies allowed.