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