Postblit isn't called on rvalue return
Ali Çehreli" <acehreli at yahoo.com>
Ali Çehreli" <acehreli at yahoo.com>
Wed Apr 24 13:53:10 PDT 2013
On Wednesday, 24 April 2013 at 11:42:01 UTC, Sebastian Graf wrote:
> For this program:
>
> import std.stdio;
>
> struct S
> {
> ubyte* b;
> ubyte buf[128];
>
> this(this)
> {
> writeln("postblit");
> }
> }
>
> auto ref makeS()
> {
> S s;
> s.b = s.buf;
> writeln("made S at ", cast(void*)&s, ", s.b == ", s.b);
> return s;
> }
>
> void main()
> {
> S s = makeS();
> writeln("got back S at ", cast(void*)&s, ", s.b == ",
> s.b);
> }
>
> I get
>
> made S at 18FC64, s.b == 18FC68
> got back S at 18FCF4, s.b == 18FC68
>
> as output for dmd 2.062. Patching s.b to point into the newly
> allocated struct in postblit is crucial here, but it seems like
> the postblit constructor isn't called, nor is there any attempt
> to optimize away the temporary in `makeS()` even with -O.
> Is this is a bug or am I doing something wrong?
First, as the local 's' in makeS() is local, it cannot be
returned by ref. So, the 'auto ref' return type of makeS()
becomes by-value.
However, rvalues are never copied in D. The compiler
automatically moves the bits of the rvalue to the left-hand side
object, and to be correct, it also elides the destructor
execution on the rvalue. (Note that this is not the RVO and NRVO
optimization that C++ "allows". This is a language feature in D.)
For that feature to be available at all, struct objects must not
have references to themselves; D explicitly makes it illegal.
So, unfortunately your S is not a valid type in D because of the
following line (.ptr is added by me):
s.b = s.buf.ptr;
Ali
More information about the Digitalmars-d-learn
mailing list