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.

Reply via email to