ref struct member function

PinDPlugga a at a.com
Fri May 14 10:00:28 UTC 2021


On Thursday, 13 May 2021 at 19:48:44 UTC, Ali Çehreli wrote:
> I was writing this example that shows a use case for the 
> problem (marked with BUG below):
> ```D
> struct Fraction {
>     auto n = 0L;
>     auto d = 1L;
>
>     // ... other bits ...
>
>     ref Fraction reduce() {
>       import std.numeric : gcd;
>
>       // v = gcd(n, d);
>       // if (v > 1) {
>       //   n /= v;
>       //   d /= v;
>       // }
>
>       return this;
>     }
>
>     // ... etc ...
> }
>
> ref foo() {
>   import std.stdio : writeln;
>   auto f = Fraction(3, 9);
>
>   // BUG: Returns reference to an object on the stack
>   return f.reduce();
> }
>
> void main() {
>   // Refers to a temporary (it would be a copy without the &)
>   auto f = &foo();
>
>   // Do some unrelated things hoping that space for dead 
> objects on
>   // the stack will be reused.
>   import std.stdio;
>   import std.random;
>   writeln("doing something else: ", uniform(0, 6));
>
>   writeln(f.d); // Access dead and overwritten object (does NOT 
> print
>                 // 9 on my system)
> }
> ```
> Putting 'return' where Steve shows makes the compiler guard us 
> against this misuse and the program thankfully does not compile.
>
> Ali

Hi thank you both for your answers. I had understood from an 
earlier chapter how this could introduce a bug, but I was 
confused because the warning suggests attaching ```return``` to 
the parameter, which is empty in the declaration.

So my next question would be how come ref based operator 
overloads are not labelled as return and do not show this warning?

``` D
struct Fraction {
     auto n = 0L;
     auto d = 1L;

     ref Fraction opUnary(string op)()
     if (op == "++") {
         n += d;
         return this;
     }
}

ref Fraction foo() {
     auto f = Fraction(1, 3);

     // Same bug as with reduce
     return ++f;
}
```


More information about the Digitalmars-d-learn mailing list