views:

111

answers:

4

Hi, I read that for user-defined types, postponing the defintion of a variable until a suitable initializer is available can lead to better performance. why?

+3  A: 

Because it means a constructor other than the default constructor is called.

X x; // Calls X()
x.Set(42);

X x(42); // Calls X(int)
Steven Sudit
I doubt you'd find much of a performance difference, though, except in more complex cases.
GMan
@GMan: True, although a deeper issue would be classes that can *only* be initialized, never assigned. These immutable classes have become much more common as of late, due to the rise of parallelism.
Steven Sudit
@Steven: But then it's not really about performance but usability. :)
GMan
@GMan: It's both. Actually, I think Neil's example is better than mine, because it shows how we're avoiding a memory allocation.
Steven Sudit
+1  A: 

You avoid running an unnecessary constructor followed by an Init call when the proper initialization data is available. And, if the code path never reaches the initialization branch you can avoid the constructor and destructor all together, plus an exception handling state setup for the unwinding.

Remus Rusanu
Good point. How often have you seen a function that declares a bunch of variables at the top, and then immediately exits because a parameter is null? (rhetorical question)
Steven Sudit
+3  A: 

Consider a string class. If we say:

string s;
....
s = "foobar";

then we have to do some work in the construction of s, and then more or less repeat the same work in the assignment. If we do:

string s( "foobar" );

we do the work once only.

Having said that, when learning C++ you should never concern yourself with issues of performance - think only about writing clear and understandable code. And in this case, initialisation with a value also wins out - code is clearer if variables are always initialised.

And BTW, the language is called C++ - cpp is the C preprocessor.

anon
Ironically, the first implementation of C++ was a translator into C; essentially just a pre-processor. :-)
Steven Sudit
@Steven No it wasn't - I used it - it was a compiler (not a translator or a pre-processor) which emitted C as it's target language. I wish this myth would die.
anon
@Neil - that's interesting to know. At least on my case my first experience with C++ was CFront (http://en.wikipedia.org/wiki/Cfront) and I believe it was in fact a pre-processor.
Otávio Décio
@Neil: A compiler which emits C would be considered a translator.
Steven Sudit
@Neil Butterworth: Umm.. how exactly compiler that emits C code (i.e. not machine code) is different from preprocessor? To me it looks like they do almost same thing...
SigTerm
@Otávio: Yes, I was referring to Cfront. Thanks for mentioning the name.
Steven Sudit
anon
@Steven - on a DEC-VAX btw. Makes me feel quite old. Sigh. @Neil - in that sense you are quite correct. However I always heard of CFront with the word preprocessor close by.
Otávio Décio
Look, it's technically both a translator and a source-to-source compiler. Cfront was more sophisticated than CPP, but it shared the common property of generating C code. This is why Cfront is often compared to preprocessors. For example, Stephen Dewhurst, who worked on Cfront and on the next few C++ implementations, casually referred to it as "essentially a preprocessor". Unfortunately, that quote was from a conversation we had while we were coworkers, so I can't link to a reference.
Steven Sudit
anon
@Neil: You do what you like, but if Dewhurst admits it was "essentially a pre-processor", then I feel quite comfortable describing it the same way. I never denied that it was technically a (source-to-source) compiler, so this is not so much a matter of actual disagreement as your being unhappy with my choice of words.
Steven Sudit
Otávio Décio
anon
In my experience, a 'translator' produces code that is (ideally) as readble as the source. It preserves comments, structure, and variable names as much as possible, like the old `p2c` translator. A compiler that targets C (or some other language) makes no attempt to produce readable output. CFront was definitely NOT a translator
Chris Dodd
A: 

For user-defined types in particular, the constructor and setting method could me arbitrarily complex and time-consuming. Taking Steven's example:

X x; // Calls X() 
x.Set(42); 

X x(42); // Calls X(int) 

... the implementation of X::X() and X::Set() might both be very time-consuming, and that's why you read that the latter can have better performance.

JaredReisinger