Class Initialization
Jonathan M Davis
jmdavisProg at gmx.com
Tue Jan 31 10:48:34 PST 2012
On Tuesday, January 31, 2012 12:07:16 Zachary Lund wrote:
> In C++, they provide a mechanism to initialize class variables to a
> passed value.
>
> class Test
> {
> int bob;
>
> public:
> Test(int jessica) : bob(jessica) { }
> };
>
> The above basically says "int this.bob = jessica;" as opposed to this:
>
> class Test
> {
> int bob;
> public:
> Test(int jessica) { bob = jessica; }
> };
>
> which basically says "int this.bob = void; bob = jessica;". Now, I'm not
> a speed freak but this is a quick and should be a painless optimization.
> D allows defaults set by the class but cannot seem to find anything to
> allow me variable initialization values. Not that it's that big of a
> deal but am I missing something?
In C++, nothing is initialized before the initializer list. Then everything is
initialized with the initializer list or with its default constructor if it
has one. Then you do whatever assignments you do in the constructor body. So,
you end up having to initialize everything in the initializer list which isn't
a primitive type if you want to avoid default-initializing the type before
assigning to it. It also prevents you from being able to call one
constructor with another.
D takes a different approach. It initializes every member variable with what
you directly initialize it with when it's declared (or the type's init value
if you don't give it a value). All of these values must be known at compile
time, which should actually allow them to be _more_ efficient than what C++ does
with default initialization in the constructor. You then do whatever
assignments you want to do in the constructor. This has the added benefit of
allowing you to call one constructor from another. e.g.
this(float param2)
{
this(5, param2, generateParam3(param2));
}
this(int param1, float param2, bool param3)
{
//...
}
_All_ variables are default initialized in D, because it's much safer to do
that, avoiding bugs with undefined behavior when you forget to initialize
something. And as with all variable initializations in D, if you really want
the extra speed of having a variable initialized with garbage before you
assign to it at some later point, you initialize it to void.
int a = void;
So, you can get all of the speed that C++ does, and it's actually more
flexible. In C++, if you couldn't initialize an object in the initialization
list (e.g. because you needed multiple lines of setup code before initializing
it), you're forced to default initialize it and then assign to it, whereas in
D, you either get a default initialized value where the value was
determined at compile time, or you initialized it to void, avoiding all
initialization cost until you actually want to assign to the variable.
I would point out though that the use of initializing to void without good
reason is generally frowned upon. It's intended for performance-critical code
where you actually need it. Outside of that, letting types be initialized to
their init values is much safer and is the preferred thing to do.
Another point to consider in the difference between construction in C++ and D
is that in C++, an object is constructed one derived type at a time. When the
base class constructor is called, the type is _only_ that base class. Not only
have the derived constructors not been called yet, but that portion of the
type hasn't been created at all. As such, it's completely unsafe to call
virtual functions. In D however, the _entire_ type is created and default
initialized before the first constructor is called. So, when a class'
constructor is called, it's already fully-formed. The constructors then have
the chance to put the object in the state that you want, but it's perfectly
safe to call virtual functions in a class' constructor in D, unlike in C++.
So, the way that objects are constructed is fundamentally different in D.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list