Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
March 05, 2015 Object as function argument | ||||
---|---|---|---|---|
| ||||
Hi, I'm a developer coming from C and I've a question about class instance as method or function parameter. In the book "The D Programming Language", I read the instance was passed by reference to functions (in the opposite of structures). I understood that it was the same object in the function and the caller. But I'm think, I was wrong because when I print the addresses of an object before the function call and inside the function, they're not the same but the changes from the function are kept in the instance. If I use the "ref" qualifier in the function declaration, the 2 addresses are the same. How do the changes work in the function? Is there a copy ? Or a "magic" trick :) ? Chris |
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Sperandio | On Thursday, 5 March 2015 at 19:35:35 UTC, Chris Sperandio wrote:
> Hi,
>
> I'm a developer coming from C and I've a question about class instance as method or function parameter.
> In the book "The D Programming Language", I read the instance was passed by reference to functions (in the opposite of structures). I understood that it was the same object in the function and the caller. But I'm think, I was wrong because when I print the addresses of an object before the function call and inside the function, they're not the same but the changes from the function are kept in the instance.
> If I use the "ref" qualifier in the function declaration, the 2 addresses are the same.
>
> How do the changes work in the function? Is there a copy ? Or a "magic" trick :) ?
>
> Chris
If you share your code, I'll be happy to take a look. Classes are reference types, so passing T for a class should pass the reference to the object.
|
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Sperandio | On 2015-03-05 19:35:34 +0000, Chris Sperandio said:
> Hi,
>
> I'm a developer coming from C and I've a question about class instance as method or function parameter.
> In the book "The D Programming Language", I read the instance was passed by reference to functions (in the opposite of structures). I understood that it was the same object in the function and the caller. But I'm think, I was wrong because when I print the addresses of an object before the function call and inside the function, they're not the same but the changes from the function are kept in the instance.
> If I use the "ref" qualifier in the function declaration, the 2 addresses are the same.
>
> How do the changes work in the function? Is there a copy ? Or a "magic" trick :) ?
>
> Chris
When you write `auto myObject = new MyObject();`
`myObject` is actually a pointer to object in GC memory. Its roughly equivalent to `struct MyObject *myobject` in C. So when you take a pointer you actually take a pointer to reference on the stack and thats why its different in the function - variable is higher up the stack.
`ref` qualifyer guaranties that you get the pointer to the same reference.
If you really need the actual pointer to object data you can use `*cast(void**)&myObject`. Compiler cannot cast object reference to `void*` but we can trick it ;)
|
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to w0rp | Below the code:
module item;
import std.stdio;
class Item
{
ulong count;
static void call1(Item item)
{
writeln("(call1) Addr: ", &item);
}
static void call2(ref Item item)
{
writeln("(call2) Addr: ", &item);
}
static Item call3(Item item)
{
writeln("(call3) Addr: ", &item);
return item;
}
static Item call4(Item item)
{
// Here, I change the count
item.count = 100;
return item;
}
}
void main()
{
auto item = new Item();
writeln("(main) Addr item=", &item);
Item.call1(item);
Item.call2(item);
auto res3 = Item.call3(item);
writeln("(main) res3 item=", &res3);
auto res4 = Item.call4(item);
writeln("(main) res4 item=", &res4);
assert(item.count == 100);
}
I get:
(main) Addr item=7FFF5D797818
(call1) Addr: 7FFF5D7977F8
(call2) Addr: 7FFF5D797818
(call3) Addr: 7FFF5D7977F8
(main) res3 item=7FFF5D797820
(main) res4 item=7FFF5D797828
On Thursday, 5 March 2015 at 19:48:38 UTC, w0rp wrote:
> On Thursday, 5 March 2015 at 19:35:35 UTC, Chris Sperandio wrote:
>> Hi,
>>
>> I'm a developer coming from C and I've a question about class instance as method or function parameter.
>> In the book "The D Programming Language", I read the instance was passed by reference to functions (in the opposite of structures). I understood that it was the same object in the function and the caller. But I'm think, I was wrong because when I print the addresses of an object before the function call and inside the function, they're not the same but the changes from the function are kept in the instance.
>> If I use the "ref" qualifier in the function declaration, the 2 addresses are the same.
>>
>> How do the changes work in the function? Is there a copy ? Or a "magic" trick :) ?
>>
>> Chris
>
> If you share your code, I'll be happy to take a look. Classes are reference types, so passing T for a class should pass the reference to the object.
|
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Sperandio | On Thursday, March 05, 2015 19:35:34 Chris Sperandio via Digitalmars-d-learn wrote:
> Hi,
>
> I'm a developer coming from C and I've a question about class
> instance as method or function parameter.
> In the book "The D Programming Language", I read the instance was
> passed by reference to functions (in the opposite of structures).
> I understood that it was the same object in the function and the
> caller. But I'm think, I was wrong because when I print the
> addresses of an object before the function call and inside the
> function, they're not the same but the changes from the function
> are kept in the instance.
> If I use the "ref" qualifier in the function declaration, the 2
> addresses are the same.
>
> How do the changes work in the function? Is there a copy ? Or a "magic" trick :) ?
MyClass c;
is a reference to an object. So, if you do &c, you're taking the address of the reference, not the object. So, it's like if you had
MyClass* c;
in C/C++ and you did &c. So, if you have
void bar()
{
auto c1 = new MyClass;
foo(c1);
}
void foo(MyClass c2)
{
}
then c1 and c2 have different addresses just like if they would if they were explictly pointers. Changing foo to
void foo(ref MyClass c2)
{
}
means that you're passing the reference itself by ref, making it essentially equivalent to
void foo(MyClass*& c2)
{
}
in C++. So, c2's address is going to be the same as c1, because they're essentially the same reference/pointer at that point. If you want the address of the object itself rather than its reference, then you need to cast it to void*. e.g. this code will print the same value for c1 and c2:
import std.stdio;
class MyClass {}
void main()
{
auto c1 = new MyClass;
writeln(cast(void*)c1);
foo(c1);
}
void foo(MyClass c2)
{
writeln(cast(void*)c2);
}
- Jonathan M Davis
|
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Ok... So, in D when I work with Object, it's like if I work with only pointers. Thus, I can return null from a function which returns an Item instance. Is it clean to write this code below ? static Item nullReturn(Item item) { // ... // and for some cases return null; } |
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Sperandio | On Thursday, 5 March 2015 at 20:08:08 UTC, Chris Sperandio wrote:
> Is it clean to write this code below ?
yup. Though remember all the downsides of null - if you try to use a null object like accessing a member, the program will be terminated.
|
March 05, 2015 Re: Object as function argument | ||||
---|---|---|---|---|
| ||||
Posted in reply to Max Klyga | On Thursday, 5 March 2015 at 19:51:09 UTC, Max Klyga wrote:
> If you really need the actual pointer to object data you can use `*cast(void**)&myObject`. Compiler cannot cast object reference to `void*` but we can trick it ;)
It can, actually. A class can define its own cast(void*) though, so the reinterpret way may be more robust. Also, I'm not sure if any of this is specified. So watch out for undefined (or underspecified) behaviour.
|
Copyright © 1999-2021 by the D Language Foundation