Taking arguments by value or by reference

Max Haughton maxhaton at gmail.com
Sat Oct 3 23:47:32 UTC 2020

On Saturday, 3 October 2020 at 23:00:46 UTC, Anonymouse wrote:
> I'm passing structs around (collections of strings) whose 
> .sizeof returns 432.
> The readme for 2.094.0 includes the following:
>> This release reworks the meaning of in to properly support all 
>> those use cases. in parameters will now be passed by reference 
>> when optimal, [...]
>> * Otherwise, if the type's size requires it, it will be passed 
>> by reference.
>> Currently, types which are over twice the machine word size 
>> will be passed by
>> reference, however this is controlled by the backend and can 
>> be changed based
>> on the platform's ABI.
> However, I asked in #d a while ago and was told to always pass 
> by value until it breaks, and only then resort to ref.
>> [18:32:16] <zorael> at what point should I start passing my 
>> structs by ref rather than by value? some are nested in 
>> others, so sizeofs range between 120 and 620UL
>> [18:33:43] <Herringway> when you start getting stack overflows
>> [18:39:09] <zorael> so if I don't need ref for the references, 
>> there's no inherent merit to it unless I get in trouble 
>> without it?
>> [18:39:20] <Herringway> pretty much
>> [18:40:16] <Herringway> in many cases the copying is merely 
>> theoretical and doesn't actually happen when optimized
> I've so far just been using const parameters. What should I be 
> using?

Firstly, the new in semantics are very new and possibly subtly 
broken (take a look at the current thread in general).

Secondly, as to the more specific question of how to pass a big 
struct around it may be helpful to look at this quick godbolt 
example (https://d.godbolt.org/z/nPvTWz). Pay attention to the 
instructions writing to stack memory (or not). A struct that big 
will be passed around on the stack, whether it gets copied or not 
depends on the semantics of the struct etc.

The guiding principle to your function parameters should be 
correctness - if I am passing a big struct around, if I want to 
take ownership of it I probably want to take it by value but if I 
want to modify it I should take it by reference (or by pointer 
but don't overcomplicate, notice in the previous example they 
lower to the same thing). If I just want to look at it, it should 
be taken by const ref if possible (D const isn't the same as C++ 
const, this may catch you out).

Const-correctness is a rule to live by especially with an big 
unwieldy struct.

I would avoid the new in for now, but I would go with const ref 
from what you've described so far.

More information about the Digitalmars-d-learn mailing list