auto ref escaping local variable

Ali Çehreli via Digitalmars-d digitalmars-d at puremagic.com
Tue Jan 24 11:16:21 PST 2017


On 01/24/2017 02:03 AM, Jonathan M Davis via Digitalmars-d wrote:
 > On Tuesday, January 24, 2017 00:47:31 Ali Çehreli via Digitalmars-d 
wrote:

 >> The problem with auto ref is that in the case of rvalues, what you have
 >> is a local variable, which makes it almost given that when it's 'auto
 >> ref', it better be 'auto ref const' because you don't want to mutate
 >> anyway because your mutations would be lost in the case of rvalues.
 >
 > If you're looking to mutate the argument that's passed in, then it 
needs to
 > be ref. If you're looking to have a copy to mutate, then it should not be
 > ref. If you don't intend to mutate it, then auto ref works just fine. It
 > just doesn't prevent you from mutating anything. And if you're using auto
 > ref and it's expected that the argument will be mutated, then it needs to
 > make sense for the result to be thrown away as would occur with an rvalue
 > argument.

Obviously, I know all of that and they are pretty complicated for new 
programmers.

I just can't imagine what the semantics of a function could be. Do you 
have an example? So, we're talking about a function that will mutate its 
argument but the caller sometimes doesn't care. Oh, this sounds like 
functions from the C era, which take null when the caller does not care.

So, is this the guideline? "Make the argument 'auto ref' when you have 
something to return in addition to the return value." If so, it's 
sub-obtimal because the 'auto ref' doesn't have the opportunity of 
bypassing operations like the C function could:

     if (arg) {
         // Do expensive operation
     }

If I guessed the semantics right, non-const 'auto ref' does not have 
that luxury.

 >> I'm under the impression (and started to write a blog post about) that
 >> the following two overloads is better than 'auto ref' (const or not).
 >> Given S is a struct,
 >>
 >>    void foo(const(S));        // Takes rvalue
 >>    void foo(ref const(S));    // Takes lvalue
 >>
 >> Those two work with all kinds of S arguments: lvalue, rvalue, imuttable,
 >> different kinds of member indirections, etc.
 >
 > I don't see why that would be better than auto ref.

Well, if I don't understand the semantics of non-const 'auto ref' then 
there is only 'auto ref const' to talk about, in which case, the two 
overloads are better because it's more explicit that one takes rvalue.

 > It's doing exactly the
 > same thing except that it's const. You're just manually doing what 
auto ref
 > does. And given how restrictive const is, I would be very slow to 
mark much
 > of anything with it unless the types are known. And if you want 
const, then
 > just use const auto ref. The only advantage of
 >
 >     void foo(const(S));        // Takes rvalue
 >     void foo(ref const(S));    // Takes lvalue
 >
 > over const auto ref is that it works with virtual functions. Otherwise,
 > you're just manually doing what const auto ref does - which scales 
horribly
 > as you add more parameters.

Yeah, the issue with non-scaling was one of the reasons why I had 
stopped turning this into a blog post.

 > Personally, most of the time, I simply don't worry about the 
performance of
 > copying. I just pass everything by value and don't use ref unless it's
 > expected that the argument's value will be used and that it will be 
given a
 > new value as part of the call (in which case, there is no non-ref 
overload).
 > If profiling indicates that there's too much of a performance hit from
 > copying structs around, then I'll look at using ref or auto ref for
 > performance, but it's not something that I do if I don't need to. It just
 > makes the code messier and more verbose - especially if you use ref 
instead
 > of auto ref.
 >
 > I also tend to not bother with const at this point. Too little works 
with it
 > for it to be worth it most of the time - especially since ranges 
don't work
 > with it. Built-in types and simple structs can work with it just 
fine, but
 > much beyond that becomes a bundle of pain really fast, and even simple
 > structs fall flat on their face once you need a postblit constructor. 
So, I
 > would _not_ be in a hurry to suggest to anyone that they start using 
const
 > ref or const auto ref anywhere.
 >
 > - Jonathan M Davis
 >

const is still engrained in my programming mind due to long exposure to 
C and C++. I guess D is proving that it's not that essential to be 
const-correct. This is similar to how private is not as strong and in 
some cases public is the default.

Ali



More information about the Digitalmars-d mailing list