in the code:
for (int i = 1; i <= 100; i++)
{
CBigObject x;
x.DoStuff ();
}
is the object x...
a) Constructed and destructed times within the for loop
b) Constructed and destructed once
c) Constructed 100 times, then 100 x's destructed at the end of the
function?
d) something else.
Its a scoping question... My vote is for a), but I'm not sure.
greg
No - it's an optimisation problem ;-). With all compiler optimisations turned
off you will get (a). With compiler optimisation on you should get (b) but it
will depend upon what the constructor/destructor actually does and whether or
not the optimiser can sus it out. Conceivably therefore you may get (d).
For example: the constructor/destructor is trivial so the optimiser puts it
in-line, inside the loop. It is then a candidate for invariant code motion
but the optimiser determines that it is not invariant and so can't move it to
before the start of the loop. The loop is then a candidate for loop
unrolling and so the constructor may get called two or three or four times in
a loop that loops a half, a third or a quarter as many times as the original.
Regards,
---------------------------------------------------------------------------
Bruce Horrocks
EASAMS Limited (...but speaking for myself)
Waters Edge, Riverside Way, Watchmoor Park, Camberley, Surrey, GU15 3PD, UK
Tel: +44 1276 686777 Tel: +44 1276 693081 (direct) Fax: +44 1276 686623
X400: S=HORROCKS,G=BRUCE,I=B,O=EASAMS LTD,P=GEC MARCONI,A=ATTMAIL,C=GB
Mailto:Bruce.H...@gecm.com
---------------------------------------------------------------------------
] Ok, this isnt a Mac specific question at all, but I'm sure you can
] answer it.
]
] in the code:
]
] for (int i = 1; i <= 100; i++)
] {
] CBigObject x;
] x.DoStuff ();
] }
]
]
] is the object x...
] a) Constructed and destructed times within the for loop
] b) Constructed and destructed once
] c) Constructed 100 times, then 100 x's destructed at the end of
] the function?
] d) something else.
]
] Its a scoping question... My vote is for a), but I'm not sure.
Vote again, it's b. Think of it as a regular variable, one with a
significant size, then run the loop a couple of thousand times. However
the memory was allocated it would be a significant speed bump, and it
would also give x a different value each time through the loop, with NO
advantage gained since you'd never be able to access the value of the
variable except within a particular pass through.
--
John Moreno
GM> Ok, this isnt a Mac specific question at all, but I'm sure you can
GM> answer it.
GM>
GM> in the code:
GM>
GM> for (int i = 1; i <= 100; i++)
GM> {
GM> CBigObject x;
GM> x.DoStuff ();
GM> }
GM>
GM>
GM> is the object x...
GM> a) Constructed and destructed times within the for loop
GM> b) Constructed and destructed once
GM> c) Constructed 100 times, then 100 x's destructed at the end of the
GM> function?
GM> d) something else.
GM>
GM> Its a scoping question... My vote is for a), but I'm not sure.
GM>
GM> greg
GM>
Compare to this:
for (int i = 1; i <= 100; i++)
{
CBigObject *x = new CBigObject();
x->DoStuff();
delete x;
}
The two loops are functionally much the same. The only difference is how the
memory is allocated. In your loop, the memory is allocated off the stack and
in my loop allocation is from the heap. In both loops the constructor is
called at the top of the loop and the destructor is called at the bottom of
the loop. Each is called 100 times.
--
\/
Robert Heller ||InterNet: Hel...@CS.UMass.EDU
http://vis-www.cs.umass.edu/~heller ||FidoNet: 1:321/153
http://netmar.com/mall/shops/heller /\
But the question was not how many times the memory is allocated, but
how many times the object is constructed. To allocate the memory,
most compilers would either (1) allocate the space on the stack once
at the beginning of the function and reuse it each time through the
loop, or (2) subtract the proper size from the stack pointer each time
through the loop to create the space for the object.
Most compilers I've seen use option (1), but option (2) really wouldn't
be that inefficient.
However, the ctor will be called at the start of the for loop each time,
and the dtor will be called at the end (assuming that the real code this
is a snippet of does something slightly more complex than what is shown;
otherwise, as others have pointed out, the ctor and dtor calls would
probably be optimized out of existence).
True not THAT inefficient - but the value of the variable wouldn't
necessarily be consistent from iteration to iteration. And it WOULD be
much more inefficient when constructing a object, which isn't as easy
(or as quick) as just moving the SP for a variable.
] However, the ctor will be called at the start of the for loop each
] time, and the dtor will be called at the end (assuming that the real
] code this is a snippet of does something slightly more complex than
] what is shown; otherwise, as others have pointed out, the ctor and
] dtor calls would probably be optimized out of existence).
Even if there wasn't a scoping problem with doing it that way, I can't
believe that b isn't something a compiler wouldn't do as part of it's
normal (minimal) optimization. As far as the scoping rules go -
allowing the creation of variables and objects inside of compound
statements is C++'s answer to Pascal's nested procedures.
--
John Moreno
> ] > Greg McPherson <rs...@minyos.its.rmit.EDU.AU> wrote:
> ] >
> ] > ] Ok, this isnt a Mac specific question at all, but I'm sure you can
> ] > ] answer it.
> ] > ]
> ] > ] in the code:
> ] > ]
> ] > ] for (int i = 1; i <= 100; i++)
> ] > ] {
> ] > ] CBigObject x;
> ] > ] x.DoStuff ();
> ] > ] }
> ] > ]
> ] > ]
> ] > ] is the object x...
> ] > ] a) Constructed and destructed times within the for loop
> ] > ] b) Constructed and destructed once
> ] > ] c) Constructed 100 times, then 100 x's destructed at the end
> ] > ] of the function?
> ] > ] d) something else.
> ] > ]
...
>
> Even if there wasn't a scoping problem with doing it that way, I can't
> believe that b isn't something a compiler wouldn't do as part of it's
> normal (minimal) optimization. As far as the scoping rules go -
> allowing the creation of variables and objects inside of compound
> statements is C++'s answer to Pascal's nested procedures.
If that optimization were performed, the semantics of the routine
would be changed completely. Try a slightly different example:
// A demon who will answer exactly one question. If you ask for
// more than one answer, though, you will be imprisoned forever
// and the demon will be freed in our universe!
class Demon {
public:
Demon(void); // Summon a demon from the abyss
~Demon(void); // Send him packing
string AnswerQuestion(const string & question); // Be careful!
};
for (int i = 1; i <= 100; i++) {
Demon d;
string answer = d.AnwerQuestion("Who's the fairest of them all?");
}
I would certainly hope my compiler would not optimize me right into
the abyss forever!
- Scott
--
Scott Howlett, how...@netcom.com
"If trees could scream, would we be so cavalier about cutting them
down? We might, if they screamed all the time, for no good reason."
] In article <1996112100...@roxboro-168.interpath.net>,
] phe...@interpath.com (John Moreno) wrote:
]
] > ] > Greg McPherson <rs...@minyos.its.rmit.EDU.AU> wrote:
] > ] >
] > ] > ] Ok, this isnt a Mac specific question at all, but I'm sure you
] > ] > ] can answer it.
] > ] > ]
] > ] > ] in the code:
] > ] > ]
] > ] > ] for (int i = 1; i <= 100; i++)
] > ] > ] {
] > ] > ] CBigObject x;
] > ] > ] x.DoStuff ();
] > ] > ] }
] > ] > ]
] > ] > ]
] > ] > ] is the object x...
] > ] > ] a) Constructed and destructed times within the for loop
] > ] > ] b) Constructed and destructed once
] > ] > ] c) Constructed 100 times, then 100 x's destructed at the
] > ] > ] end of the function?
] > ] > ] d) something else.
] > ] > ]
] ...
] >
] > Even if there wasn't a scoping problem with doing it that way, I
] > can't believe that b isn't something a compiler wouldn't do as part
] > of it's normal (minimal) optimization. As far as the scoping rules
] > go - allowing the creation of variables and objects inside of
] > compound statements is C++'s answer to Pascal's nested procedures.
]
] If that optimization were performed, the semantics of the routine
] would be changed completely. Try a slightly different example:
]
-snip-
] I would certainly hope my compiler would not optimize me right into
] the abyss forever!
Well, instead of arguing about it any more, I checked it out. And what
do you know? I was WRONG. So, I'll just shut up and keep my (mistaken)
opinions to myself.
--
John Moreno
No - it's not just an optimisation problem! Unless the compiler knows at
this point exactly what the constructor does and exactly what DoStuff()
does, it MUST construct and destruct 100 times in this loop. The
compiler can not optimize. Why? Look at the following example:
Class CBigObject {
public:
CBigObject();
~CBigObject() {}
void DoStuff();
private:
int mFresh;
};
CBigObject::CBigObject()
{
mFresh = 1;
}
void CBigObject::DoStuff()
{
if(mFresh)
{
printf("changing mFresh to False");
mFresh = 0;
}
}
Now, the way the for() loop is defined, each time through you expect a
fresh CBigObject so you should see "Changing mFresh to False" 100 times.
But if the compiler optimized this by only creating one of these then
you only see it once. Since real code may have memory issues at stake
here, the compiler is NOT free to do this optimization. Since the
compiler doesn't necessarily know what DoStuff() is going to do, it can't
assume that calling it multiple times on one instance is the same as
calling it one time on mulitple instances. Hence, the compiler does
exactly what you asked for and creates and destroys 100 CBigObject's.
Of course, if both the ctor and DoStuff() are defined as inline, the
compiler may "be able to tell" that it can get away with one ctor/dtor
call but otherwise, its got no choice.
bill vareka
This is what I said. Go and re-read my posting.
Regards,
---------------------------------------------------------------------------
Bruce Horrocks
EASAMS Limited (...but speaking for myself)
Waters Edge, Riverside Way, Watchmoor Park, Camberley, Surrey, GU15 3PD, UK
Tel: +44 1276 686777 Tel: +44 1276 693043 (direct) Fax: +44 1276 686623
As the original poster, I'm stunned at the response to the question.
After I posted it, I thought "gee, the answer's obvious. I should have
just stopped and thought for a second."
Obviously the code must have the effect of creating and destroying 100
CBigObjects. Whether or not the compiler actually allocates and
de-allocates 100 blocks of memory, or just re-uses the same piece of RAM
is up to it's optimization algorithm.
I would expect the constructor/destructor fns to be called 100 times, no
matter what optimization is occuring.
I get the impression you all roughly agree with this, but somehow are
still arguing.
thanks for an interesting read,
greg
> As the original poster, I'm stunned at the response to the question.
> After I posted it, I thought "gee, the answer's obvious. I should have
> just stopped and thought for a second."
>
> Obviously the code must have the effect of creating and destroying 100
> CBigObjects. Whether or not the compiler actually allocates and
> de-allocates 100 blocks of memory, or just re-uses the same piece of RAM
> is up to it's optimization algorithm.
> I would expect the constructor/destructor fns to be called 100 times, no
> matter what optimization is occuring.
>
> I get the impression you all roughly agree with this, but somehow are
> still arguing.
>
> thanks for an interesting read,
> greg
Hey, Greg, This is the net. :-)
Let no post go unargued.
Cheers,
Lou Pecora
code 6343
Naval Research Lab
Washington DC 20375
USA
== My views are not those of the U.S. Navy. ==
------------------------------------------------------------
Check out the 4th Experimental Chaos Conference Home Page:
http://natasha.umsl.edu/Exp_Chaos4/
------------------------------------------------------------