initialization lists ?

Daniel919 Daniel919 at web.de
Thu Jul 5 03:09:35 PDT 2007


> One, your example is a little wrong: that FAQ also mentions that "There is 
> no performance difference if the type of x_ is some built-in/intrinsic type, 
> such as int."  So you should be using a class type instead.

So I guess that's what I wondered about: The optimizer can turn these 
simple assignments into sth like a initialization list.

> Two, D doesn't allow for the same kind of object semantics that C++ does. 
> C++ allows classes to have their memory allocated inside other classes, 

Classes in D are always stored by ref. that's the point, right ?
MyClass foo = new MyClass(); <- this allocates an instance of MyClass 
somewhere on the heap and puts a ref to it into foo. So sizeof(foo) is 
always constant.

> which is why using initialization lists are faster: rather than creating 
> that temp object and copying it into the memory inside 'this', it just runs 
> the constructor for the internal object on the memory already inside 'this'.

   class Foo {
     AnotherClass v;
     Foo(AnotherClass t) { v = t; };
   };
   Foo f = new Foo(a);

The assignment way:
While creating the instance of Foo for f...
1. The internal object v gets created inside the instance of f.
2. The temp instance t gets created somewhere outside the actual class 
instance of f.
3. a is copied into t.
4. t is copied into v.

Using initialization lists:
While creating the instance of Foo for f...
1. The internal object v gets created inside the instance of f.
2. a is copied into v.

> D only allows classes to be allocated on the heap (well, they can be 
> allocated on the stack in some circumstances, but not in the general case 
> like in C++).  Therefore, if one of your class's members is another class 
> that needs to be constructed, it's going to have to be new'ed anyway, so 
> there's no way to optimize it.

Because (in the example above) the instance of v can be located 
somewhere on the heap (v only holds the reference to it), so it doesn't 
have to be within the instance of f.
And the copy of reference can be treated like c++ optimizers do for 
built-in/intrinsic types. a (reference to an instance of Foo) is copied 
into v directly, without the need for a temporary object, holding the 
passed-in ref.
Or even if it isn't optimized away: Copying of refs is trivial compared 
to copying of the class's data.

> D does, however, have structs which can have their memory allocated inside 
> other aggregates (structs, classes, unions).  In this case, when you use the 
> "fake" struct ctor (a static S opCall), the compiler can optimize the call 
> to this function and it becomes as fast as a simple assignment to the 
> struct's members.  (Structs are rumored to be getting ctors soon, so 
> hopefully it will be less arcane and "magical"-looking.) 

I wonder: Then this would be the only case where initialization lists 
could come into play for D ?

   struct MyStruct {
     MyStruct parent; //error, discussed below
     int id;
     int value;

     this(MyStruct t, int i, int j) {
       v = t;
       id = i;
       value = j;
     }
   }

But no wait, "MyStruct v;" this is not working, because it's an 
unresolveable forward reference.
Makes sense, if you try to figure out how much bits to allocate for a 
single instance of MyStruct:

id +4, value +4, but hmm... how much for v ? (goto beginning of line)
It's an infinite recursion.

So one has to use a ptr instead (which always has a const size, 
independed of MyStruct):
   struct MyStruct {
     MyStruct* v;
     ...
   }

And then it's an equal situation as for classes (and their refs):
In the ctor the simple assignment of the ptr can be optimized away (like 
c++ compilers do for built-in/intrinsic types).
Or even if it isn't optimized away: Copying of ptrs is trivial compared 
to copying of the struct's data.


Did I get things right ? Otherwise please correct me.


Daniel



More information about the Digitalmars-d mailing list