this(this) / opAssign

monarch_dodra monarchdodra at gmail.com
Thu Jan 10 15:28:38 PST 2013


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.


More information about the Digitalmars-d-learn mailing list