www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - D Classes Passed By Reference or Value?

reply "Brandon Ragland" <brandon callmemaybe.com> writes:
Hi All, I'm a bit confused as to how Classes in D are passed in 
arguments and returns.

Take this for example:

class MyClass{
int x = 2;
}

And then in app.d

ref MyClass doStuff(){
MyClass mc = new MyClass() // Heap allocation, using new....
return mc;
}

The above fails, as "escaping reference to local variable" 
however, this was created using new.... Not understanding what 
the deal is, this should be a valid heap allocated object, and 
therefore, why can I not pass this by reference? I don't want 
this to be a local variable...

So this begs the question: Are Classes (Objects) passed by 
reference already?

-Brandon
Aug 16 2015
next sibling parent reply "Alex Parrill" <initrd.gz gmail.com> writes:
On Sunday, 16 August 2015 at 22:31:02 UTC, Brandon Ragland wrote:
 Hi All, I'm a bit confused as to how Classes in D are passed in 
 arguments and returns.

 Take this for example:

 class MyClass{
 int x = 2;
 }

 And then in app.d

 ref MyClass doStuff(){
 MyClass mc = new MyClass() // Heap allocation, using new....
 return mc;
 }

 The above fails, as "escaping reference to local variable" 
 however, this was created using new.... Not understanding what 
 the deal is, this should be a valid heap allocated object, and 
 therefore, why can I not pass this by reference? I don't want 
 this to be a local variable...

 So this begs the question: Are Classes (Objects) passed by 
 reference already?

 -Brandon
Classes are reference types, a la Java/C#. class MyClass { int x = 5; } void main() { auto c1 = new MyClass(); auto c2 = c1; c1.x = 123; assert(c2.x == 123); }
Aug 16 2015
parent reply "Brandon Ragland" <brandon callmemaybe.com> writes:
On Sunday, 16 August 2015 at 22:35:15 UTC, Alex Parrill wrote:
 On Sunday, 16 August 2015 at 22:31:02 UTC, Brandon Ragland 
 wrote:
 Hi All, I'm a bit confused as to how Classes in D are passed 
 in arguments and returns.

 Take this for example:

 class MyClass{
 int x = 2;
 }

 And then in app.d

 ref MyClass doStuff(){
 MyClass mc = new MyClass() // Heap allocation, using new....
 return mc;
 }

 The above fails, as "escaping reference to local variable" 
 however, this was created using new.... Not understanding what 
 the deal is, this should be a valid heap allocated object, and 
 therefore, why can I not pass this by reference? I don't want 
 this to be a local variable...

 So this begs the question: Are Classes (Objects) passed by 
 reference already?

 -Brandon
Classes are reference types, a la Java/C#. class MyClass { int x = 5; } void main() { auto c1 = new MyClass(); auto c2 = c1; c1.x = 123; assert(c2.x == 123); }
Thanks, That makes more sense. Though it does make the ref method signature unclear, as it only applies to literals at this point? Would you still need the ref signature for method parameters for classes to avoid a copy? Such that I could work on the class itself, and not a copy. //This is reference? void doStuff(ref MyClass mc){ return; } or would this also be a valid reference type: //This is a copy? void doStuff(MyClass mc){ return; }
Aug 16 2015
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/16/2015 04:13 PM, Brandon Ragland wrote:

 That makes more sense. Though it does make the ref method
 signature unclear, as it only applies to literals at this
 point?
As long as the returned object will be valid after the function leaves, it can be anything: one of the ref parameters, a module-level variable, etc.
 Would you still need the ref signature for method parameters
 for classes to avoid a copy? Such that I could work on the
 class itself, and not a copy.
Obviously, you meant "the object itself."
 //This is reference?
 void doStuff(ref MyClass mc){
 return;
 }
Yes, that's a reference to a class variable. Since class variables are references anyway, unless intended, there is one too many level of indirection there. (Although, it is valid and it may exactly be what is needed.)
 or would this also be a valid reference type:

 //This is a copy?
 void doStuff(MyClass mc){
 return;
 }
That's the normal way of doing it. mc is class reference to an object that was presumably created somewhere else. Ali
Aug 16 2015
parent reply "Brandon Ragland" <brandon callmemaybe.com> writes:
On Sunday, 16 August 2015 at 23:31:46 UTC, Ali Çehreli wrote:
 On 08/16/2015 04:13 PM, Brandon Ragland wrote:

 That makes more sense. Though it does make the ref method
 signature unclear, as it only applies to literals at this
 point?
As long as the returned object will be valid after the function leaves, it can be anything: one of the ref parameters, a module-level variable, etc.
 Would you still need the ref signature for method parameters
 for classes to avoid a copy? Such that I could work on the
 class itself, and not a copy.
Obviously, you meant "the object itself."
 //This is reference?
 void doStuff(ref MyClass mc){
 return;
 }
Yes, that's a reference to a class variable. Since class variables are references anyway, unless intended, there is one too many level of indirection there. (Although, it is valid and it may exactly be what is needed.)
 or would this also be a valid reference type:

 //This is a copy?
 void doStuff(MyClass mc){
 return;
 }
That's the normal way of doing it. mc is class reference to an object that was presumably created somewhere else. Ali
If I understand you correctly than: void doStuff(MyClass mc){ mc.x = 7; } Would be working with the reference to the object instantiated elsewhere. This would NOT be a copy of the object. That would mean that (ref MyClass mc) is the equivalent to a pointer to a pointer (sorta, though these are references, same idea follows). -Brandon
Aug 16 2015
parent "Nicholas Wilson" <iamthewilsonator hotmail.com> writes:
On Sunday, 16 August 2015 at 23:40:41 UTC, Brandon Ragland wrote:
 On Sunday, 16 August 2015 at 23:31:46 UTC, Ali Çehreli wrote:
 On 08/16/2015 04:13 PM, Brandon Ragland wrote:

 That makes more sense. Though it does make the ref method
 signature unclear, as it only applies to literals at this
 point?
As long as the returned object will be valid after the function leaves, it can be anything: one of the ref parameters, a module-level variable, etc.
 Would you still need the ref signature for method parameters
 for classes to avoid a copy? Such that I could work on the
 class itself, and not a copy.
Obviously, you meant "the object itself."
 //This is reference?
 void doStuff(ref MyClass mc){
 return;
 }
Yes, that's a reference to a class variable. Since class variables are references anyway, unless intended, there is one too many level of indirection there. (Although, it is valid and it may exactly be what is needed.)
 or would this also be a valid reference type:

 //This is a copy?
 void doStuff(MyClass mc){
 return;
 }
That's the normal way of doing it. mc is class reference to an object that was presumably created somewhere else. Ali
If I understand you correctly than: void doStuff(MyClass mc){ mc.x = 7; } Would be working with the reference to the object instantiated elsewhere. This would NOT be a copy of the object. That would mean that (ref MyClass mc) is the equivalent to a pointer to a pointer (sorta, though these are references, same idea follows). -Brandon
Yes. void doStuff(ref MyClass a, ref MyClass b, ref MyClass c, bool d) { if (d) b = a; else c = a; } void main(string[] args) { auto a = new MyClass(); a.x = 1; auto b = new MyClass(); b.x = 2; auto c = new MyClass(); c.x = 3; assert(a !is b); assert(a.x == 1); assert(a !is c); assert(b.x == 2); assert(c !is b); assert(c.x == 3); doStuff(a,b,c,true); assert(a is b); assert(b.x == 1); b.x = 2; assert( a.x == 2); assert(a !is c); assert(c.x == 3); doStuff(a,b,c,false); assert(a is c); assert(c.x == 2); }
Aug 16 2015
prev sibling parent "Alex Parrill" <initrd.gz gmail.com> writes:
On Sunday, 16 August 2015 at 22:31:02 UTC, Brandon Ragland wrote:
 ref MyClass doStuff(){
 MyClass mc = new MyClass() // Heap allocation, using new....
 return mc;
 }
This attempts to return a reference to the _variable_ `mc`, not a reference to the class. Just remove `ref` from the function signature.
Aug 16 2015