digitalmars.D.learn - New With Struct and Getting Class Object Pointers
- Vijay Nayar (40/40) Sep 30 2018 I have two brief questions.
- rikki cattermole (2/16) Sep 30 2018 Yes. Uses a compiler hook to call into the GC, like with everything else...
- Nicholas Wilson (23/64) Sep 30 2018 the variable `a` is a pointer (well, actually reference) to the
- Vijay Nayar (26/40) Sep 30 2018 Is there a way to either have a constant reference to a class
- Alex (37/61) Sep 30 2018 I think, what you are facing here, is the different notion of
- Vijay Nayar (7/47) Sep 30 2018 That pretty much hits the nail on the head, and you're exactly
- Nicholas Wilson (11/14) Sep 30 2018 Alex has mentioned Rebindable, which is the answer to your first
- Vijay Nayar (11/25) Oct 03 2018 Thanks everyone for the insight. I also finished reading
I have two brief questions. Code that uses "new" to create struct objects appears to compile and run. Is this an actual language feature, to get structs on the heap? void main() { struct S {int data = 1;} S* s1 = new S(); S* s2 = s1; S s3 = *s1; // Still copies on assignment. s3.data = 2; assert(s1.data != s3.data); } Second question. const class variables may not be re-assigned, so if you need a variable that may be reassigned, but may never modify the underlying object, a const pointer can be useful. However, it seems that when gets the address of a class variable, you do not get the underlying address of the class object. How do you get a pointer to the underlying class object? Example of the problem: void main() { import std.stdio; class A { int data = 3; } A a = new A(); void f(A a) { a.data = 4; writeln("&a = ", &a, ", a.data = ", a.data); } f(a); writeln("&a = ", &a, ", a.data = ", a.data); } // Output: &a = 7FFEA6BA3158, a.data = 4 // Addresses are different, from different class variables. &a = 7FFEA6BA3180, a.data = 4 // But the same underlying class object. Especially if I'm several levels down the call stack, how do I get a pointer to the underlying class object?
Sep 30 2018
On 30/09/2018 8:29 PM, Vijay Nayar wrote:I have two brief questions. Code that uses "new" to create struct objects appears to compile and run. Is this an actual language feature, to get structs on the heap? void main() { struct S {int data = 1;} S* s1 = new S(); S* s2 = s1; S s3 = *s1; // Still copies on assignment. s3.data = 2; assert(s1.data != s3.data); }Yes. Uses a compiler hook to call into the GC, like with everything else.
Sep 30 2018
On Sunday, 30 September 2018 at 07:29:00 UTC, Vijay Nayar wrote:I have two brief questions. Code that uses "new" to create struct objects appears to compile and run. Is this an actual language feature, to get structs on the heap? void main() { struct S {int data = 1;} S* s1 = new S(); S* s2 = s1; S s3 = *s1; // Still copies on assignment. s3.data = 2; assert(s1.data != s3.data); } Second question. const class variables may not be re-assigned, so if you need a variable that may be reassigned, but may never modify the underlying object, a const pointer can be useful. However, it seems that when gets the address of a class variable, you do not get the underlying address of the class object. How do you get a pointer to the underlying class object? Example of the problem: void main() { import std.stdio; class A { int data = 3; } A a = new A(); void f(A a) { a.data = 4; writeln("&a = ", &a, ", a.data = ", a.data); } f(a); writeln("&a = ", &a, ", a.data = ", a.data); } // Output: &a = 7FFEA6BA3158, a.data = 4 // Addresses are different, from different class variables. &a = 7FFEA6BA3180, a.data = 4 // But the same underlying class object. Especially if I'm several levels down the call stack, how do I get a pointer to the underlying class object?the variable `a` is a pointer (well, actually reference) to the underlying data. void main() { import core.stdc.stdio; class A { int data = 3; } A a = new A(); void f(A a) { a.data = 4; printf("&a = %p, a = %p, a.data=%d\n", &a, a,a.data); } f(a); printf("&a = %p, a = %p, a.data=%d\n", &a,a, a.data); } &a = 0x7ffd0800acb8, a = 0x7fd6b05b0000, a.data=4 &a = 0x7ffd0800acd0, a = 0x7fd6b05b0000, a.data=4 The stack ^ the heap^ data on the heap^ The address of the variable a on the stack has different values across function calls, its value (the reference to the class data) remains the same, as does the data itself.
Sep 30 2018
On Sunday, 30 September 2018 at 09:16:42 UTC, Nicholas Wilson wrote:On Sunday, 30 September 2018 at 07:29:00 UTC, Vijay Nayar wrote:Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer? For example: void main() { class Thing {} class ThingSaver { // A const(Thing) could not be changed in setThing(). const(Thing)* t; void setThing(in Thing thing) { t = thing; // ERROR converting to pointer type! } const(Thing) getThing() const { return *t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); const(Thing) t2 = saver.getThing(); }Second question. const class variables may not be re-assigned, so if you need a variable that may be reassigned, but may never modify the underlying object, a const pointer can be useful. However, it seems that when gets the address of a class variable, you do not get the underlying address of the class object.&a = 0x7ffd0800acb8, a = 0x7fd6b05b0000, a.data=4 &a = 0x7ffd0800acd0, a = 0x7fd6b05b0000, a.data=4 The stack ^ the heap^ data on the heap^ The address of the variable a on the stack has different values across function calls, its value (the reference to the class data) remains the same, as does the data itself.
Sep 30 2018
On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote:Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer? For example: void main() { class Thing {} class ThingSaver { // A const(Thing) could not be changed in setThing(). const(Thing)* t; void setThing(in Thing thing) { t = thing; // ERROR converting to pointer type! } const(Thing) getThing() const { return *t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); const(Thing) t2 = saver.getThing(); }I think, what you are facing here, is the different notion of const, as used from C++. The reasoning about it is described for example here: http://jmdavisprog.com/articles/why-const-sucks.html Jonathan is much better therein as I am. However, there are approaches to solve what you want to do. For example, there is a Rebindable around: https://dlang.org/library/std/typecons/rebindable.html ´´´ import std.stdio; import std.typecons; void main() { class Thing {int dummy; } class ThingSaver { /* A const(Thing) could not be changed in setThing(), but a Rebindable can be reassigned, keeping t const. */ Rebindable!(const Thing) t; void setThing(in Thing thing) { t = thing; // No pointers in use :) } const(Thing) getThing() const { return t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); //saver.t.dummy = 5; fails as expected. const(Thing) t2 = saver.getThing(); } ´´´ I hope, I got your idea right...
Sep 30 2018
On Sunday, 30 September 2018 at 10:28:25 UTC, Alex wrote:On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote:That pretty much hits the nail on the head, and you're exactly right about where my understanding was coming from (C++). In fact, I'm moving a lot of code from C++ to D and finding equivalents for a lot of high-performance index classes, which end up using this kind of pattern. Now I need to take the time to grok this article!Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer?I think, what you are facing here, is the different notion of const, as used from C++. The reasoning about it is described for example here: http://jmdavisprog.com/articles/why-const-sucks.html Jonathan is much better therein as I am. However, there are approaches to solve what you want to do. For example, there is a Rebindable around: https://dlang.org/library/std/typecons/rebindable.html ´´´ import std.stdio; import std.typecons; void main() { class Thing {int dummy; } class ThingSaver { /* A const(Thing) could not be changed in setThing(), but a Rebindable can be reassigned, keeping t const. */ Rebindable!(const Thing) t; void setThing(in Thing thing) { t = thing; // No pointers in use :) } const(Thing) getThing() const { return t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); //saver.t.dummy = 5; fails as expected. const(Thing) t2 = saver.getThing(); } ´´´ I hope, I got your idea right...
Sep 30 2018
On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote:Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer?Alex has mentioned Rebindable, which is the answer to your first question. To answer your second question, no class A {} A a: `a` is always a (possibly null) reference to a class instance. You can have pointers to class references (which is what `&a` gives you) but that has two indirections between the variable and the data, which if you want high perf is probably not what you are looking for.
Sep 30 2018
On Sunday, 30 September 2018 at 11:11:09 UTC, Nicholas Wilson wrote:On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote:Thanks everyone for the insight. I also finished reading Jonathan's article: http://jmdavisprog.com/articles/why-const-sucks.html I've run into just about every single problem described there, but had no idea just how deep the problem goes. So it was a depressing read, but I'm glad to have the deeper understanding. I'm definitely more open now to see what "__mutable" could offer as was discussed at DConf2018, though I'm curious about how it would remain compatible with "immutable".Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer?Alex has mentioned Rebindable, which is the answer to your first question. To answer your second question, no class A {} A a: `a` is always a (possibly null) reference to a class instance. You can have pointers to class references (which is what `&a` gives you) but that has two indirections between the variable and the data, which if you want high perf is probably not what you are looking for.
Oct 03 2018