On Sunday, 3 November 2013 at 15:38:30 UTC, Luís Marques wrote:
Hi,
Most of the time my D code has been high-level, so I had never
considered the following issue. Imagine you have a struct A as
a member of a class/struct X (here a struct, to ensure the dtor
is called):
struct A
{
int v;
this(int v)
{
this.v = v*2;
}
~this()
{
writefln("~A(%d)", v);
}
}
struct X
{
A a;
this(int v)
{
a = A(v);
writeln("-");
}
}
void main()
{
X x = X(42);
}
Output:
~A(0)
-
~A(84)
That is, because we don't have C++'s colon initialization
syntax, we are paying the cost of initializing (and then
destroying) X.a before we assign to it with "a = A(v)" in X's
ctor. This seems to be the case even with @disable A.this(),
which here does not seem to do anything (does not prevent the
default/implicit initialization of X.a, before it is assigned
A(v) ).
If C++ distinguishes between initialization and assignment to
avoid this issue, is there a reason why D can avoid making the
distinction? That is a performance issue. How about
correctness? For instance:
struct A
{
void* mem;
@disable this();
this(int v)
{
mem = malloc(v);
}
~this()
{
free(mem);
}
}
Now we can't have an A as a member of X? (it would free a null
pointer)
How have you solved these cases? Do you change it to a PIMPL?
What if that's not desirable? What if you don't want to break
encapsulation / cleanliness too much? Etc. Is there a good
general solution for this issue?
for actual version of dmd, you can use this trick :)
struct A
{
int v;
void opAssign(int v) {
this.v = v;
}
static int opCall(int v) {
return v * 2;
}
~this()
{
writefln("~A(%d)", v);
}
}