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