Is there any reason to use non-ref foreach?

bauss jj_1337 at live.dk
Fri Aug 31 12:52:17 UTC 2018


On Friday, 31 August 2018 at 09:59:20 UTC, Dukc wrote:
> For me, it seems that for generality you should always add ref 
> into foreach loop variable. The reason is this:
>
> import std.experimental.all;
>
> struct NoCopies
> {   @disable this(this);
>     int payload;
> }
>
> void main()
> {   auto range = new NoCopies[20];
>     foreach(const ref el; range) el.payload.writeln;
> }
>
> Without ref qualifier in el, this won't work because it would 
> make a copy. Unlike ref as a function argument, it does not 
> enforce refness:
>
> import std.experimental.all;
>
> void main()
> {   auto range = iota(20).map!(x => x + 2);
>     foreach(const ref el; range) el.writeln;
> }
>
> This compiles, even though range elements are rvalues.
>
> This seems to imply, for me, that for generality one should 
> always use ref in foreach loop variables. If the vairable has 
> to be guarded against changes, it should const ref, not 
> unqualified.
>
> But considering unqualified is the default, I am probably 
> missing something here. Performance?

It makes sense in your simplified examples, but in practice it 
doesn't, because it will depend on each situation, what type of 
data you're enumerating etc.

And I bet you there are some gotchas using just ref.

In reality you're micro-optimizing something that doesn't require 
it.

Remember that basically the difference is this.

foreach (i; values) {
  ...
}

for (int _ = 0; _ < values; _++)
{
     auto i = values[_];

     ...
}

VS

foreach (ref i; values) {
  ...
}

for (int _ = 0; _ < values; _++)
{
     auto i = &values[_];

     ...
}

So basically ... Instead of copying the value, you're just 
copying the address.

I can't see the benefit other than added complexity.


More information about the Digitalmars-d-learn mailing list