www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Classes new'd inside for loop are all the same instance?

reply lobo <swamplobo gmail.com> writes:
I am confused, which is normal, but I'd appreciate some help :-)

If I create N classes in a for loop they are all the same 
instance. I would expect each to be a unique instance of the 
class. See the code below

---

class C {}
void main() {
     import std.stdio;

     auto c1 = new C();
     writefln("c1:%s", &c1); // OK, instance c1 is unique

     auto c2 = new C(); // OK, instance c2 is unqiue
     writefln("c2:%s", &c2);

     foreach(a; 0..10) {

         C c = new C(); // All instances are the same object with 
the same address?
         writefln("c:%s", &c);

     }
}
---

This isn't what I expected. What could I be doing wrong?

Thanks,
lobo
Sep 08 2016
next sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 8 September 2016 at 12:24:48 UTC, lobo wrote:
 I am confused, which is normal, but I'd appreciate some help :-)

 If I create N classes in a for loop they are all the same 
 instance. I would expect each to be a unique instance of the 
 class. See the code below

 ---

 class C {}
 void main() {
     import std.stdio;

     auto c1 = new C();
     writefln("c1:%s", &c1); // OK, instance c1 is unique

     auto c2 = new C(); // OK, instance c2 is unqiue
     writefln("c2:%s", &c2);

     foreach(a; 0..10) {

         C c = new C(); // All instances are the same object 
 with the same address?
         writefln("c:%s", &c);

     }
 }
 ---

 This isn't what I expected. What could I be doing wrong?

 Thanks,
 lobo
I don't have time to explain at the moment, but change the `&c` to `cast(void*)c` and you will see what you expect. I will post an explanation soon.
Sep 08 2016
parent lobo <swamplobo gmail.com> writes:
On Thursday, 8 September 2016 at 12:28:55 UTC, Meta wrote:
 On Thursday, 8 September 2016 at 12:24:48 UTC, lobo wrote:
 [...]
I don't have time to explain at the moment, but change the `&c` to `cast(void*)c` and you will see what you expect. I will post an explanation soon.
Thanks for the blazingly quick reply! :) Please post the explanation when you get time because I'd love to know what is really happening. bye, lobo
Sep 08 2016
prev sibling next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 09/09/2016 12:24 AM, lobo wrote:
 I am confused, which is normal, but I'd appreciate some help :-)

 If I create N classes in a for loop they are all the same instance. I
 would expect each to be a unique instance of the class. See the code below

 ---

 class C {}
 void main() {
     import std.stdio;

     auto c1 = new C();
     writefln("c1:%s", &c1); // OK, instance c1 is unique

     auto c2 = new C(); // OK, instance c2 is unqiue
     writefln("c2:%s", &c2);

     foreach(a; 0..10) {

         C c = new C(); // All instances are the same object with the
 same address?
         writefln("c:%s", &c);

     }
 }
 ---

 This isn't what I expected. What could I be doing wrong?

 Thanks,
 lobo
Well for starters C is already a pointer ;) cast(void*) should do the trick not &.
Sep 08 2016
prev sibling parent reply drug <drug2004 bk.ru> writes:
08.09.2016 15:24, lobo пишет:
 I am confused, which is normal, but I'd appreciate some help :-)

 If I create N classes in a for loop they are all the same instance. I
 would expect each to be a unique instance of the class. See the code below

 ---

 class C {}
 void main() {
     import std.stdio;

     auto c1 = new C();
     writefln("c1:%s", &c1); // OK, instance c1 is unique

     auto c2 = new C(); // OK, instance c2 is unqiue
     writefln("c2:%s", &c2);

     foreach(a; 0..10) {

         C c = new C(); // All instances are the same object with the
 same address?
         writefln("c:%s", &c);

     }
 }
 ---

 This isn't what I expected. What could I be doing wrong?

 Thanks,
 lobo
&c is address of the variable c, that is allocated on the stack and has the same address on every iteration cast(void*)c return the value of variable c that is address of a class instance and is different for every iteration in other words &c is address of pointer cast(void*)c is the pointer itself
Sep 08 2016
next sibling parent lobo <swamplobo gmail.com> writes:
On Thursday, 8 September 2016 at 12:36:29 UTC, drug wrote:
 08.09.2016 15:24, lobo пишет:
[...]
&c is address of the variable c, that is allocated on the stack and has the same address on every iteration cast(void*)c return the value of variable c that is address of a class instance and is different for every iteration in other words &c is address of pointer cast(void*)c is the pointer itself
Got it, thank you :)
Sep 08 2016
prev sibling parent Meta <jared771 gmail.com> writes:
On Thursday, 8 September 2016 at 12:36:29 UTC, drug wrote:
 &c is address of the variable c, that is allocated on the stack 
 and has the same address on every iteration
 cast(void*)c return the value of variable c that is address of 
 a class instance and is different for every iteration

 in other words
 &c is address of pointer
 cast(void*)c is the pointer itself
Yes, thank you. I'll just add that in D (as well as in Java and C#), while classes are always reference types and the type of `c` in `C c = new C();` will be reported as C, it's actually more of a hidden type, "reference to a C". These references are always passed by value. c (reference to a C) value pointed at by c on the stack on the heap [0x00002450] ... [0x00008695] | ^ |________________________| For example: class C { string name; } void setName(C c) { c.name = "bob"; //This change will be seen outside setName c = new C("jim"); //This change will not } void setNameRef(ref C c) { c.name = "bob"; //This change will be seen outside setNameRef c = new C("jim"); //This change will also be seen outside setNameRef } In `setName` c (which is actually a reference to a C) cannot be rebound as the reference is passed by value into the function. However, c.name can still be modified as you are modifying the value pointed at by the reference, not the reference itself. In `setNameRef` you can modify both, because c is passed by ref, meaning that there is now a double-indirection. Thus, you can modify both c and the value pointed at by c.
Sep 08 2016