Thread overview
Class Initialization
Jan 31, 2012
Zachary Lund
Jan 31, 2012
Jonathan M Davis
Jan 31, 2012
Andrej Mitrovic
Jan 31, 2012
Trass3r
Jan 31, 2012
bls
Jan 31, 2012
Trass3r
Jan 31, 2012
H. S. Teoh
Feb 01, 2012
Vijay Nayar
January 31, 2012
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?
January 31, 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
January 31, 2012
On 1/31/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> In D however, the _entire_ type is created and default initialized before the first constructor is called.

I was reading the C++ Object Model book recently (well, I'm still reading) and was amazed at how many edge-cases there are in C++, and how lucky I am to be using D. Well, minus the Optlink that is. :)
January 31, 2012
On Tue, Jan 31, 2012 at 08:49:25PM +0100, Andrej Mitrovic wrote:
> On 1/31/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > In D however, the _entire_ type is created and default initialized before the first constructor is called.
> 
> I was reading the C++ Object Model book recently (well, I'm still reading) and was amazed at how many edge-cases there are in C++, and how lucky I am to be using D. Well, minus the Optlink that is. :)

OOP in C++ is so broken that I have given up on OO in C++ altogether. I just write C++ code as "C with classes". I have come to hold the opinion that real OO cannot be done properly in C++ (not without lots and lots of pain, hacks, workarounds, and bandages, anyway).  OO in Java is much saner.

But I'm glad to say that OO in D is turning out to be much better so far.  It's what C++ should have been but failed to be.


T

-- 
My program has no bugs! Only unintentional features...
January 31, 2012
> I was reading the C++ Object Model book recently (well, I'm still
> reading) and was amazed at how many edge-cases there are in C++, and
> how lucky I am to be using D. Well, minus the Optlink that is. :)

*whispers gee dee ceeeeeeee*
January 31, 2012
On 01/31/2012 12:41 PM, Trass3r wrote:
> *whispers gee dee ceeeeeeee*

windows binaries please.......
January 31, 2012
>> *whispers gee dee ceeeeeeee*
>
> windows binaries please.......

Seek and you shall find.
https://bitbucket.org/goshawk/gdc/downloads
February 01, 2012
The basic idea is that in D, any statically identifiable information (known at compile-time), can be used to assign class members as they are declared.

Any time a new object is created, it will take those default values specified for its members.

This is a small example demonstrating default initialization for both structs and classes.  In fact, compared to the version of C++ I used to use (I can't speak for C++11), the syntax is far more consistent and less verbose than initializer lists.

struct Dummy {
    int field1 = 10;
    int field2 = 11;
}

class MyClass {
    int a = 0;
    int[] b = [1, 2, 3];
    Dummy c = Dummy(4, 5);

    int d = 6;

    this() {
    }

    this(int val) {
        d = val;
    }
}

void main() {
    MyClass first = new MyClass();
    MyClass second = new MyClass(7);

    assert(first.a == 0);
    assert(first.b == [1, 2, 3]);
    assert(first.c.field1 == 4);
    assert(first.d == 6);

    assert(second.c.field1 == 4);
    assert(second.d == 7);
}

You are correct that in the case of the second constructor, two assignments effectively take place, d = 6, then d = 7.  However, I do not think the compiler can know what you intend to do in the constructor, or even that you will not use the default value of d before reassigning it.

In short, I think the optimization would tend to become more of a source of problems than a gain in performance in any meaningful way.

 - Vijay

On Tue, 31 Jan 2012, 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?
>