www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Object as function argument

reply "Chris Sperandio" <christian.sperandio gmail.com> writes:
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
Mar 05 2015
next sibling parent reply "w0rp" <devw0rp gmail.com> writes:
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.
Mar 05 2015
parent "Chris Sperandio" <christian.sperandio gmail.com> writes:
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.
Mar 05 2015
prev sibling next sibling parent reply Max Klyga <max.klyga gmail.com> writes:
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 ;)
Mar 05 2015
parent "anonymous" <anonymous example.com> writes:
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.
Mar 05 2015
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
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
Mar 05 2015
parent reply "Chris Sperandio" <christian.sperandio gmail.com> writes:
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;
   }
Mar 05 2015
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Mar 05 2015