On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
And what should I use, this(this) or opAssign? I thougth that it is unimportant,
but that changed my mind: http://dpaste.dzfl.pl/36ce3688

The default generated opAssign will postblit the other struct over itself, then destroy it's own (old) body (if a postblit occured):

import std.stdio;

//----
struct S
{
        this(this) {
                writeln("this(this)");
        }
        ~this() {
                writeln("~this");
        }
}

void main()
{
        S a, b;

        writeln("Start");
        a = b;
        writeln("Finish");
}
//----
Produces
//----
Start
this(this) //Postblit a new copy
~this      //Destroy the old body
Finish
~this
~this
//----

This is a very sweet deal: If you write a constructor (and optionally a destructor), then that's all you need for D to make things consistent. For example:

//----
import std.stdio;

struct S
{
        int* p;
        this(int i)
        {
            p = new int;
            *p = i;
        }
        this(this)
        {
            int* p2 = new int;
            *p2 = *p;
            p = p2;
        }
}

void main()
{
        S a = S(1);
        S b = S(2);

        writeln("Start");
        a = b;
        assert(*a.p == 2);
        assert(a.p != b.p);
        writeln("Finish");
}
//----
Here, the default generate opAssign is *not* "stupid" and will not straight up assign the pointers. After the assignments, each struct will still have their own personal payload!

Now to answer your question:
If your object is a POD, the no need for opAssign.
If your object has a constructor, then the default opAssign should remain consistent with your construcor's behavior...

...BUT: you can still implement it yourself if (and only if) you need a custom behavior. In the above example, opAssign "worked", but it did needlessly re-alocate. This is the kind of situation where writing an opAssign is worth it.

Reply via email to