Bug 10146 – ref on return is ignored

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-05-23T03:42:00Z
Last change time
2013-05-23T04:18:16Z
Assigned to
nobody
Creator
rswhite4

Comments

Comment #0 by rswhite4 — 2013-05-23T03:42:34Z
The 'ref' by 'getA' is ignored. [code] import std.stdio; struct A { public: int id; this(int id) { writeln("CTor ", id); this.id = id; } this(this) { writeln("Postblit ", this.id); this.id *= 2; } ~this() { writeln("DTor ", this.id); } } class B { private: A _a; public: this() { this._a = A(42); } ref A getA() { writeln("Return A"); return this._a; } } void main() { B b = new B(); A a = b.getA(); } [/code] Expected Output: ---- CTor 42 DTor 0 Return A DTor 42 ---- Current Output: ---- CTor 42 DTor 0 Return A Postblit 42 DTor 84 DTor 42 ----
Comment #1 by maxim — 2013-05-23T04:03:04Z
D does not have references like C++. Each time you assign return value to a struct variable, refness is wiped out. The only cases when returning by ref matter, is when returned value is also returned by caller by ref or casted to pointer.
Comment #2 by rswhite4 — 2013-05-23T04:08:43Z
I expected that in this case opAssign is called, not the postblit, beause I return by ref and assign then the ref to a new value. But if you change A to this: [code] struct A { public: int id; this(int id) { writeln("CTor ", id); this.id = id; } this(this) { writeln("Postblit ", this.id); this.id *= 2; } void opAssign(ref const A a) { writeln("opAssign L: ", a.id); this.id = a.id; } void opAssign(const A a) { writeln("opAssign R ", a.id); memcpy(&this, &a, A.sizeof); } ~this() { writeln("DTor ", this.id); } } [/code] You see still the same output, no call of opAssign by 'getA': ---- CTor 42 opAssign R 42 DTor 42 Return A Postblit 42 DTor 84 DTor 42 ---- Or did I miss something important here?
Comment #3 by maxim — 2013-05-23T04:14:52Z
(In reply to comment #2) > I expected that in this case opAssign is called, not the postblit, beause I > return by ref and assign then the ref to a new value. Actually no, because refness here does not matter. You return by ref, but get not a ref in the caller. You don't assign ref to a new value either. You have A a = Initializer; which calls copy constructor.
Comment #4 by rswhite4 — 2013-05-23T04:18:16Z
That is absolute strange, but thanks for the explanation.