rvalues -> ref (yup... again!)

Manu turkeyman at gmail.com
Sat Mar 24 00:20:09 UTC 2018


On 23 March 2018 at 16:58, Jonathan M Davis via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
> On Friday, March 23, 2018 23:35:29 MattCoder via Digitalmars-d wrote:
>> Well, to be honest I still can't understand why would you want to
>> pass a RValue as reference.
>
> Well, it's frequently the case that you don't want to copy an object if you
> don't have to - especially in the gaming world, where every ounce of
> performance matters. If a function accepts an argument by ref, then no copy
> is made, but then you have to pass an lvalue, making it really annoying to
> call the function when what you have is an rvalue. On the other hand, if the
> function doesn't accept its argument by ref, then you can pass an rvalue
> (and it will be moved, making that efficient), but then lvalues get copied
> when that's often not what you want. C++'s solution to this was rvalue
> references.

Ummm... rvalue-references are something completely different.
rval-ref's are C++'s solution to move semantics.
C++ just simply accepts rvalues passed to const& args. It makes a temp
and passes the ref, as you expect.


> That way, as long as the parameter is const, it can accept both
> rvalues and lvalues, and it won't copy unless it has to. The closest
> analogue that D has to this is auto ref, which requires templates, which may
> or may not be acceptable.

auto-ref == template function, which by definition is NOT an
extern(C++) function. auto-ref may also resolve to NOT a ref, which
means a move... data structures that are large (ie, a vector or
matrix) still have to copy a bunch of memory, even if the copy is
algorithmically 'cheap'.


> In many cases, it works great, whereas in others,
> it doesn't work at all (e.g. virtual functions), and it can result in
> template bloat.

And templates, that's another case where it fails.
auto-ref is something else unrelated to this topic, and it's useful in
a different set of cases for a different set of uses/reasons. It's got
nothing to do with this.


> The whole situation is complicated by the fact that sometimes it's actually
> faster to pass by value and copy the argument, even if it's an lvalue.

The api author wouldn't have made the arg a ref in that case.


> Passing by const& can often result in unnecessary copies if anywhere in the
> chain passes the object by value, whereas if it's passed by value, the same
> object can often be moved multiple times, avoiding any copies**.

**avoiding __calls to the copy constructor__. The memory is likely to
still be moved around a bunch of times.
The case you're thinking of is when values are *returned* by value, in
that case, copy elision is possible, and the result can be constructed
in place. That's a completely unrelated problem... you don't do
return-by-ref ;)


> It's my
> understanding that prior to C++11, it was considered best practice to pass
> by const& as much as possible to avoid copies but that after C++11 (which
> added move constructors), it's often considered better to pass by value,
> because then in many cases, the compiler can move the object instead of
> copying it**.

** Assuming the object is tiny, but has an expensive copy constructor.
In the case where an object is large (and has a primitive, or no copy
constructor) it doesn't change the situation; you still wanna pass a
big thing by ref in all cases; ie, vector/matrix.


> So, C++ gives you control over which you do, and it's not
> necessarily straightforward as to which you should use (though plenty of
> older C++ programmers likely just use const& all over the place out of
> habit).

D gives you the same set of options; except that passing args by ref
is a PITA in D, and ruins your code.


More information about the Digitalmars-d mailing list