Efficient way to pass struct as parameter

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Jan 2 18:45:48 UTC 2018


On Tuesday, January 02, 2018 18:21:13 Tim Hsu via Digitalmars-d-learn wrote:
> I am creating Vector3 structure. I use struct to avoid GC.
> However, struct will be copied when passed as parameter to
> function
>
>
> struct Ray {
>      Vector3f origin;
>      Vector3f dir;
>
>      @nogc @system
>      this(Vector3f *origin, Vector3f *dir) {
>          this.origin = *origin;
>          this.dir = *dir;
>      }
> }
>
> How can I pass struct more efficiently?

When passing a struct to a funtion, if the argument is an rvalue, it will be
moved rather than copied, but if it's an lvalue, it will be copied. If the
parameter is marked with ref, then the lvalue will be passed by reference
and not copied, but rvalues will not be accepted (and unlike with C++,
tacking on const doesn't affect that). Alternatively, if the function is
templated (and you can add empty parens to templatize a function if you want
to), then an auto ref parameter will result in different template
instantiations depending on whether the argument is an lvalue or rvalue. If
it's an lvalue, then the template will be instantiated with that parameter
as ref, so the argument will be passed by ref and no copy will be made,
whereas if it's an rvalue, then the parameter will end up without having
ref, so the argument will be moved. If the function isn't templated and
can't be templated (e.g. if its a member function of a class and you want it
to be virtual), then you'd need to overload the function with overloads that
have ref and don't have ref in order to get the same effect (though the
non-ref overload can simply forward to the ref overload). That does get a
bit tedious though if you have several parameters.

If you want to guarantee that no copy will ever be made, then you will have
to either use ref or a pointer, which could get annoying with rvalues (since
you'd have to assign them to a variable) and could actually result in more
copies, because it would restrict the compiler's abilities to use moves
instead of copies.

In general, the best way is likely going to be to use auto ref where
possible and overload functions where not. Occasionally, there is talk of
adding something similar to C++'s const& to D, but Andrei does not want to
add rvalue references to the language, and D's const is restrictive enough
that requiring const to avoid the copy would arguably be overly restrictive.
It may be that someone will eventually propose a feature with semantics that
Andrei will accept that acts similarly to const&, but it has yet to happen.
auto ref works for a lot of cases though, and D's ability to do moves
without a move constructor definitely reduces the number of unnecessary
copies.

See also:

https://stackoverflow.com/questions/35120474/does-d-have-a-move-constructor

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list