digitalmars.D.learn - this(this) / opAssign
- Namespace (66/66) Jan 10 2013 Is it expected behaviour that this code compiles and prints:
- monarch_dodra (74/77) Jan 10 2013 The default generated opAssign will postblit the other struct
- Era Scarecrow (23/24) Jan 10 2013 I think it is. Postblit 'this(this)' occurs while initializing a
- Namespace (4/4) Jan 10 2013 Without a declared opAssign, this
- monarch_dodra (5/9) Jan 10 2013 If there is no user declared opAssign, then opAssign is
- Namespace (4/15) Jan 11 2013 And that was what I did not know and could not find anywhere. So
- David Nadlinger (7/11) Jan 10 2013 Think of it like this: Blit means bit-by-bit copy, so a postblit
- monarch_dodra (4/7) Jan 10 2013 BTW, answered to the best of my abilities, taking into account
- Namespace (3/10) Jan 10 2013 It is private, sorry.
- monarch_dodra (7/19) Jan 10 2013 Yeah, but if you re-arrange the tests, then you get opposite
- monarch_dodra (3/20) Jan 10 2013 Sorry:
Is it expected behaviour that this code compiles and prints: this(this) this(this) ? [code] import std.stdio; static if (!is(typeof(writeln))) alias writefln writeln; struct vec2f { public: float x, y; this(this) { writeln("this(this)"); } } void main() { vec2f v1 = vec2f(0, 1); vec2f v2 = vec2f(2, 3); v2 = v1; vec2f v3 = v2; } [/code] while this code [code] import std.stdio; static if (!is(typeof(writeln))) alias writefln writeln; struct vec2f { public: float x, y; this(this) { writeln("this(this)"); } ref vec2f opAssign(ref const vec2f v) { writeln("opAssign"); this.x = v.x; this.y = v.y; return this; } } void main() { vec2f v1 = vec2f(0, 1); vec2f v2 = vec2f(2, 3); v2 = v1; vec2f v3 = v2; } [/code] prints: opAssign this(this) ? 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
Jan 10 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/36ce3688The 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.
Jan 10 2013
On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:Is it expected behaviour that this code compiles and prints:I think it is. Postblit 'this(this)' occurs while initializing a variable from one, rather than copying. Which you also can compare against move symantics. Correct me if i'm wrong. struct S { this(this) {writeln("this(this)"); } void opAssign(ref S s) {writeln("opAssign ref/copy");} void opAssign(S s) {writeln("opAssign move");} } //postblit S s1; S s2 = s1; //opAssign ref (copy) S s3; s3 = s1; //opAssign S (Move) S func() {return S();} s3 = func(); output: this(this) opAssign ref/copy opAssign move
Jan 10 2013
Without a declared opAssign, this S s3; s3 = s1; also calls the postblit. That is strange.
Jan 10 2013
On Thursday, 10 January 2013 at 23:37:14 UTC, Namespace wrote:Without a declared opAssign, this S s3; s3 = s1; also calls the postblit. That is strange.If there is no user declared opAssign, then opAssign is implemented in terms of postblit. It's designed that way. This is kind of like C++'s copy and swap idiom, but built into the language.
Jan 10 2013
On Thursday, 10 January 2013 at 23:49:40 UTC, monarch_dodra wrote:On Thursday, 10 January 2013 at 23:37:14 UTC, Namespace wrote:And that was what I did not know and could not find anywhere. So it is enough if I declare a postblit. And yes, benchmarks are hard. ;)Without a declared opAssign, this S s3; s3 = s1; also calls the postblit. That is strange.If there is no user declared opAssign, then opAssign is implemented in terms of postblit. It's designed that way. This is kind of like C++'s copy and swap idiom, but built into the language.
Jan 11 2013
On Thursday, 10 January 2013 at 23:37:14 UTC, Namespace wrote:Without a declared opAssign, this S s3; s3 = s1; also calls the postblit. That is strange.Think of it like this: Blit means bit-by-bit copy, so a postblit is a function that is invoked on the result of every bit-by-bit copy operation. The default behavior for struct assignment is precisely to copy over the contents, so it makes sense for the postblit to be invoked in that case. David
Jan 10 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/36ce3688BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
Jan 10 2013
On Thursday, 10 January 2013 at 23:30:35 UTC, monarch_dodra wrote:On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:It is private, sorry. Here as public: http://dpaste.dzfl.pl/ab3c7a5cAnd what should I use, this(this) or opAssign? I thougth that it is unimportant, but that changed my mind: http://dpaste.dzfl.pl/36ce3688BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
Jan 10 2013
On Thursday, 10 January 2013 at 23:35:19 UTC, Namespace wrote:On Thursday, 10 January 2013 at 23:30:35 UTC, monarch_dodra wrote:Yeah, but if you re-arrange the tests, then you get opposite results... http://dpaste.dzfl.pl/fork/c52f290a Benchmarking is hard. You could try maybe viewing the disassembly instead?On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:It is private, sorry. Here as public: http://dpaste.dzfl.pl/ab3c7a5cAnd what should I use, this(this) or opAssign? I thougth that it is unimportant, but that changed my mind: http://dpaste.dzfl.pl/36ce3688BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
Jan 10 2013
On Friday, 11 January 2013 at 00:02:48 UTC, monarch_dodra wrote:On Thursday, 10 January 2013 at 23:35:19 UTC, Namespace wrote:Sorry: http://dpaste.dzfl.pl/9ff9b84aOn Thursday, 10 January 2013 at 23:30:35 UTC, monarch_dodra wrote:Yeah, but if you re-arrange the tests, then you get opposite results... http://dpaste.dzfl.pl/fork/c52f290aOn Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:It is private, sorry. Here as public: http://dpaste.dzfl.pl/ab3c7a5cAnd what should I use, this(this) or opAssign? I thougth that it is unimportant, but that changed my mind: http://dpaste.dzfl.pl/36ce3688BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
Jan 10 2013