Search code examples
d

Difference between 'const ref' and 'in'?


I'm trying to understand the difference between const ref and in, specially when it comes to performance.

  1. I know that in is equivalent to const scope, but what does the scope stor­age class means that ref­er­ences in the pa­ra­me­ter can­not be es­caped (e.g. as­signed to a global vari­able). mean? example code is welcome.

  2. How do I decide between const ref and in when implementing a function? I know with ref the object doesn't get copied because it's a reference, but is the same true with in?


Solution

  • 1) the scope parameter storage class means that you're not allowed to escape a reference to the parameter. Example:

    Object glob;
    
    struct S
    {
        Object o;
        void foo(scope Object o)
        {
             this.o = o; // Not allowed! 'o' must not be escaped
             glob = o; // ditto
        }
    }
    

    Note that DMD is not very good at detecting this. The above example currently compiles, but is not allowed.

    scope is most useful for delegate parameters:

    void foo(scope void delegate() dg)
    {
        /* use dg */
    }
    
    void main()
    {
        int i;
        foo({ ++i; });
    }
    

    In the above example, no closure needs to be allocated for the anonymous function even though it has an upvalue, because foo "guarantees" (it is the compiler's job...) that the delegate isn't escaped. DMD currently does implement this optimization.

    2) I think the idea is that when both const and scope is used, the compiler could theoretically pass by reference or value at will, which is why the in shortcut is useful. DMD doesn't take advantage of this right now, but it's a handy shortcut nevertheless, and it has some documentation value.

    In short, in won't currently gain you any performance unless it's used on a delegate. ref can gain you some performance with large structs or static arrays. When ref is used for performance reasons, const is often used to document (and enforce) that the ref is not used to update the original value.