www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Class Initialization

reply Zachary Lund <admin computerquip.com> writes:
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?
Jan 31 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
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
Jan 31 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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. :)
Jan 31 2012
parent bls <bizprac orange.fr> writes:
On 01/31/2012 12:41 PM, Trass3r wrote:
 *whispers gee dee ceeeeeeee*

windows binaries please.......
Jan 31 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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...
Jan 31 2012
prev sibling next sibling parent Trass3r <un known.com> writes:
 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*
Jan 31 2012
prev sibling next sibling parent Trass3r <un known.com> writes:
 *whispers gee dee ceeeeeeee*

windows binaries please.......

Seek and you shall find. https://bitbucket.org/goshawk/gdc/downloads
Jan 31 2012
prev sibling parent Vijay Nayar <vnayar wgen.net> writes:
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?

Feb 01 2012