ref arguments

Jeremie Pelletier jeremiep at gmail.com
Mon Sep 21 17:52:06 PDT 2009


Saaa wrote:
> Jeremie Pelletier wrote:
> 
>> You cannot have static array be ref or out. You must use int[] arr instead 
>> and let the caller specify the length.
>>
>> Array in D are already references to their data, it's a 8bytes (or 16bytes 
>> on x64) value containing a pointer and a length.
> 
> Ok, this I got correct :)
> 
>> So the following prototype: void func(<none>/in/ref/out int[] arr);
>>
>> would have the following semantics:
>>
>> "<none>" copies the array reference, the referenced data is mutable. 
>> Modifying the local reference does not change the caller's reference.
> 
> Modifying the local referenced data does not change the caller's referenced 
> data.
> So only if the referenced data is mutated, a copy will be made?
> Test seems to back this up.

What I meant is that modifying the local reference does not change the 
caller's reference, but both references point to the same data.

>> "in" copies the array reference, the local reference AND the referenced 
>> data are immutable in the method's scope.
> 
> What, there is a difference between <none> and "in" ??
> Where can I about read this?
> In the example "int foo(int x, ..." on the functions page x is "in".
> Are we maybe talking about a different D? D1
> I really really wish to understand this stuff.
> <info> I know about how in c a function stack is created.

I don't think theres a difference in D1, in D2 there is:

void Foo(in int[] bar);
here typeof(bar).stringof would say const(int[]).

http://digitalmars.com/d/2.0/function.html

"If no storage class is specified, the parameter becomes a mutable copy 
of its argument."

>> "ref" passes a reference to the caller's array reference, the referenced 
>> data is mutable. Modifying the local reference also changes the caller's 
>> reference.
> 
> Same as <none> except that it doesn't create a copy on mutate?

Not the same, no storage class will make a copy of the reference, which 
points to the same data as the caller's reference. "ref" makes a 
reference to the caller's reference, so you can modify it *and* the data 
it points to.

Here's an example:

void main() {
     int[] arr = new int[64];
     arr[0] = 10;

     foo(arr);

     assert(arr.length == 10); // True because foo changed our reference 
with its own
}

void foo(ref int[] arr) {
     assert(arr[0] == 10); // True because arr points to the same data 
as the caller's

     arr = new int[10];
}

This is the difference between being able to modify the array data and 
the array reference.

>> "out" passes a reference to the caller's array reference. The referenced 
>> array reference is zeroed and can be modified by the local reference.
> 
> Compared to returning a locally(to the function) created array, here
> no allocation might be needed if the passed array is big enough.

"out" does not create the array data, only a reference to a null array 
reference in the caller's frame. You still need to allocate data for the 
array. Take the above example and change ref to out, the assert in foo 
would fail because arr is set to a null reference, but the assert in 
main would succeed because foo modified it.

>> If you want a mutable reference to an immutable view on the referenced 
>> data, use const(int)[], which can also be ref or out.
> 
> out const(int)[] will create a array of zero's which you cannot change?

No, it will nullify the reference it is given allowing the method to 
assign a new reference to it for the caller to use, but wont be able to 
modify its data after assigning the reference.

> Why isn't there a nice table about this?
> columns: local reference/data with/without mutation, caller reference/data 
> with/without mutation
> rowns: <none>, in, out, ref
> cells: array.ptr/length/data
> Or, where should I put it after creating it.

I had to learn it through trial and error myself :) If you do make such 
a table you could submit it as an improvement in bugzilla.

>> void  func(in/out/ref int i)
>>
>> "<none>" would be a mutable copy.
>> "in" would be immutable copy.
> I can't get over the idea that in and none aren't the same
> Really, D1? :D
> In my test program I can change local i using "in"
> 
>> "out" is a reference to the caller's int initialized to 0.
> 
>> "ref" is a reference to the caller's int.
> 
>> "in" and "const" are only really useful with types which are already 
>> references, such as pointers, arrays and objects.
> 
> Hope I got it right.. 

Oops, I was talking in the context of D2, where 'in' is an alias for 
'const scope'.


More information about the Digitalmars-d-learn mailing list