this is not an lvalue

Adam D. Ruppe via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Dec 15 07:29:13 PST 2016


On Thursday, 15 December 2016 at 13:59:05 UTC, Andrey wrote:
> Thanks it works, but where should I use the ref?

Only when you need it, break the habit of using it everywhere.

If it is a value type and you want modifications to the variable 
itself be seen outside the function, use it:

void foo(ref int something) {
    something++;
}

void main() {
   int a = 1;
   foo(a);
   assert(a == 2);
}

Since int is value and you want to see the change to the local 
outside the function, ref is used. However, notice:

void foo(int[] arr) {
    arr[0] = 5;
}

void main() {
    int[2] a = [1, 2];
    foo(a[]);
    assert(a[0] == 5);
}

No need for ref there, because the slice is already a reference 
to its contents. However, if I wanted to *append* to the slice 
and see that length change outside, ref may be appropriate.



This brings me to classes: interfaces and class objects in D are 
already automatically pointers internally, just like slices.

void foo(Object o) { /* already like Object* in C++ */
    o.modify();
}

void main() {
    Object o = new Object();
    foo(o);
    // o has been modified
}


No need for ref to see changes to the object's internals outside. 
However, if you want to rebind the object:

void foo(ref Object o) { /* now like Object** in C++ */
    o = new Object();
}

void main() {
   Object o;
   foo(o);
   // o represents the new Object
}

ref is needed there - this is changing the variable itself, not 
what is inside it.



With structs, it depends on what you are doing with it - are you 
changing the variable itself or something inside it? And what is 
inside.

struct Foo {
    int a;
}


That Foo acts just like int, so use or don't use ref as if it was 
an int.


struct Foo {
    int[] a;
}

That one is just like a slice, no need to `ref` that unless you 
want to change the outer portion. The contents are implicitly 
referenced and not copied.


struct Foo {
    int[4] a;
}


Well, this is a value type again, but bigger. Still, I'd say 
follow the same rule as plain `int` - only ref that if you need 
modifications to be seen outside the function.


struct Foo {
    ubyte[1024 * 1024] oneMegabyte;
}


OK, you might want to ref that one just because the copy to the 
function may be expensive and the compiler is not necessarily 
going to optimize that (BUT the compiler MIGHT optimize it! If 
the function gets inlined and it isn't modified, it may compile 
to the same thing anyway. Still, I'd probably ref that myself, or 
wrap it up in pointers or maybe even a class for its interface.)



General rule of thumb: if you are refing for performance, 
actually check it before and after first, ref isn't always faster.


More information about the Digitalmars-d-learn mailing list