Ref parameter: intended behavior or bug?
Regan Heath
regan at netmail.co.nz
Wed Aug 22 03:18:50 PDT 2007
Mike Parker wrote:
> Bill Baxter wrote:
>> Mike Parker wrote:
>>> I knocked up a sample program to demonstrate reference parameters,
>>> then got a result that wasn't at all what I expected:
>>>
>>> ====================================
>>>
>>> import std.stdio;
>>>
>>> struct MyStruct
>>> {
>>> ubyte[] contents;
>>> }
>>>
>>> class MyClass
>>> {
>>> ubyte[] contents;
>>> }
>>>
>>> void structDefault(MyStruct ms)
>>> {
>>> writefln("Struct default: %d", ms.sizeof);
>>> }
>>>
>>> void structRef(ref MyStruct ms)
>>> {
>>> writefln("Struct ref: %d", ms.sizeof);
>>> }
>>>
>>> void classDefault(MyClass mc)
>>> {
>>> writefln("Class default: %d", mc.sizeof);
>>> }
>>>
>>> void main()
>>> {
>>> MyStruct ms;
>>> MyClass mc = new MyClass;
>>> structDefault(ms);
>>> structRef(ms);
>>> classDefault(mc);
>>> }
>>> ==================================
>>>
>>> Here's the output:
>>>
>>> Struct default: 8
>>> Struct ref: 8
>>> Class default: 4
>>>
>>> The first and last are what I thought they would be, but I expected
>>> the Struct ref line to output 4, since it's supposed to be a ref
>>> parameter. I assume this to be a bug, but want to make sure there's
>>> not something intended going on.
>>
>> 'ref' is not a type constructor in D, it is a storage class.
>> .sizeof gives the size of the type. The storage class shouldn't
>> affect that.
>
> But it's a bit inconsistent, is it not? Consider this function:
>
> void structPtr(MyStruct* ms)
> {
> writefln("Struct ptr: %d", ms.sizeof);
> }
>
> This will print 4.
Of course, you're asking for the size of a pointer here and a pointer on
a 32 bit system is _always_ 32 bits or 4 bytes.
> Why should the behavior of 'ref' be any different
> than that of '*'?
Because 'ref' is not '*'. To turn it around; Why should the behaviour
of 'ref' be the same as '*'?
Is the only point of having 'ref' to allow you to pass variables without
& at the call site?
I believe the main reason for 'ref' was/is to allow you to modify the
variable being passed.
So what advantage does 'ref' have over '*'?
If you ask me, in D, 'ref' has perhaps 1 small advantage, and 1 large
liability.
The advantage:
void foo(ref int a) { a = 5; } //cleaner syntax
void foo(int* a) { *a = 5; }
Consider a struct however:
struct Foo { int a; }
void foo(ref Foo f) { f.a = 5; }
void foo(Foo* f) { f.a = 5; } //identical syntax
Granted you still have:
struct Foo { int a; }
void foo(ref Foo f) { f = <some other Foo>; } //cleaner syntax
void foo(Foo* f) { *f = <some other Foo>; }
However, the liability (IMO):
Which of these functions modifies 'foo'?
Foo foo;
bar(foo);
baz(foo);
You can't tell without inspecting the function signatures. Whereas with
pointers:
Foo foo;
bar(&foo);
baz(foo);
It's quite clear, unless of course baz is passing by reference ;)
> If I want the size of the type, I would use
> MyStruct.sizeof.
I think the concept of passing by reference is that when you pass by ref
the parameter _is_ the original variable in every possible way. The
compiler might be using a proxy object to implement this, it might not
be, IANACW. As such when you ask for the size of a ref parameter you're
asking for the size of the original variable, which in this case is the
size of the struct itself.
Regan
More information about the Digitalmars-d-learn
mailing list