On Monday, 19 November 2012 at 05:22:38 UTC, Jonathan M Davis wrote:
On Monday, November 19, 2012 06:01:55 Rob T wrote:

postblit constructors and opAssign aren't really related. The postblit constructor is used when a _new_ instance is being constructed (it plays the same role as a copy constructor in C++). opAssign overloads the assignment operator and is only used when the assignment operator is used, which does _not_ happen when contstructing a new instance but only when replacing the
value of an instance with that of another.

Is this correct? From a implementation point of view it looks like opAssign is related to postblit in that it does call postblit first.
From the spec:
Struct assignment t=s is defined to be semantically equivalent to:
      t = S.opAssign(s);
    where opAssign is a member function of S:
    S* opAssign(S s)
    {   ... bitcopy *this into tmp ...
      ... bitcopy s into *this ...
      ... call destructor on tmp ...
      return this;
    }

It does not say postblit as well, but it does call it.
When assigning one object into another it will first blit, then custom postblit if you have written one. A benefit of this is, if you want deep copy semantics and postblit does the work to provide it - you do not need an opAssign at all, as your postblit will be called. I think this is a step up over C++.

The example below prints:
----------------------------------------------
Begin assign
postblit A
End assign
----------------------------------------------

import std.stdio;
import std.traits;

struct A {
  this(this) { c = c.dup; writeln("postblit A"); }
  char[] c;

}
struct B { A a; }
struct C { B b; }
struct D { C c; }

void main() {
  D d1, d2;
  d1.c.b.a.c = ['a','b','c'];
  writeln("Begin assign");
  d2 = d1;
  writeln("End assign");
}

Reply via email to