digitalmars.D.learn - Storing a reference
- Yuxuan Shui (19/19) Sep 01 2016 I just figured out how to store a reference:
- Rene Zwanenburg (20/39) Sep 01 2016 This will allocate a closure. A struct definition inside a
- Yuxuan Shui (6/29) Sep 01 2016 I think my approach is probably better, because I believe
- Rene Zwanenburg (14/19) Sep 01 2016 That's true, but you can ensure the same thing for the wrapper:
- Steven Schveighoffer (11/42) Sep 01 2016 Referring to a null object is not a problem. Your program crashes
- Yuxuan Shui (3/16) Sep 01 2016 Makes sense. Thanks!
I just figured out how to store a reference: safe: auto x(ref int a) { struct A { ref int xa() { return a; } } return A(); } void main() { import std.stdio; int b = 10; auto a = x(b); a.xa = 20; writeln(b); //Prints 20 } I have no idea if this is a right thing to do. Can someone tell me if this is idiomatic D, and whether there're any catches to this method or not? Thanks.
Sep 01 2016
On Thursday, 1 September 2016 at 19:37:25 UTC, Yuxuan Shui wrote:I just figured out how to store a reference: safe: auto x(ref int a) { struct A { ref int xa() { return a; } } return A(); } void main() { import std.stdio; int b = 10; auto a = x(b); a.xa = 20; writeln(b); //Prints 20 } I have no idea if this is a right thing to do. Can someone tell me if this is idiomatic D, and whether there're any catches to this method or not? Thanks.This will allocate a closure. A struct definition inside a function has a hidden context / closure pointer, unless it's a static struct. There is nothing like a ref variable in D. If you want to refer to something someplace else, use a pointer. You can create a pointer wrapper which acts like a reference (untested): auto toRef(ref T value) { return Ref!T(&value); } struct Ref(T) { private T* value; property ref T _value() { return *value; } alias _value this; } Note that D's pointer syntax is a bit friendlier than C++'s: the dot operator works fine on pointers. A good reason to use the Ref wrapper is to forward arithmetic operations to the wrapped value.
Sep 01 2016
On Thursday, 1 September 2016 at 20:28:03 UTC, Rene Zwanenburg wrote:On Thursday, 1 September 2016 at 19:37:25 UTC, Yuxuan Shui wrote:I think my approach is probably better, because I believe (correct me if I'm wrong): 1) it will never refer to a null object. 2) after DIP1000 is implemented we will be able to make sure there will be no dangling reference.[...]This will allocate a closure. A struct definition inside a function has a hidden context / closure pointer, unless it's a static struct. There is nothing like a ref variable in D. If you want to refer to something someplace else, use a pointer. You can create a pointer wrapper which acts like a reference (untested): auto toRef(ref T value) { return Ref!T(&value); } struct Ref(T) { private T* value; property ref T _value() { return *value; } alias _value this; } Note that D's pointer syntax is a bit friendlier than C++'s: the dot operator works fine on pointers. A good reason to use the Ref wrapper is to forward arithmetic operations to the wrapped value.
Sep 01 2016
On Thursday, 1 September 2016 at 20:38:13 UTC, Yuxuan Shui wrote:I think my approach is probably better, because I believe (correct me if I'm wrong): 1) it will never refer to a null object.That's true, but you can ensure the same thing for the wrapper: struct Ref() { disable this(); this(T* value) { assert(value !is null); this.value = value; } // rest same as before }2) after DIP1000 is implemented we will be able to make sure there will be no dangling reference.I'm not very familiar with the details of DIP1000, so I can't comment on that.
Sep 01 2016
On 9/1/16 4:38 PM, Yuxuan Shui wrote:On Thursday, 1 September 2016 at 20:28:03 UTC, Rene Zwanenburg wrote:Referring to a null object is not a problem. Your program crashes ungracefully, but does not corrupt memory. However, in either approach, it can easily end up being a dangling pointer. But to refer to a null location is quite easy: int *foo; // null ptr auto a = x(*foo); assert(&a.xa() == null); Your approach is less desirable because of the closure to point at a given reference which can be had with just a reference. Needless allocation. -SteveOn Thursday, 1 September 2016 at 19:37:25 UTC, Yuxuan Shui wrote:I think my approach is probably better, because I believe (correct me if I'm wrong): 1) it will never refer to a null object. 2) after DIP1000 is implemented we will be able to make sure there will be no dangling reference.[...]This will allocate a closure. A struct definition inside a function has a hidden context / closure pointer, unless it's a static struct. There is nothing like a ref variable in D. If you want to refer to something someplace else, use a pointer. You can create a pointer wrapper which acts like a reference (untested): auto toRef(ref T value) { return Ref!T(&value); } struct Ref(T) { private T* value; property ref T _value() { return *value; } alias _value this; } Note that D's pointer syntax is a bit friendlier than C++'s: the dot operator works fine on pointers. A good reason to use the Ref wrapper is to forward arithmetic operations to the wrapped value.
Sep 01 2016
On Thursday, 1 September 2016 at 21:07:36 UTC, Steven Schveighoffer wrote:On 9/1/16 4:38 PM, Yuxuan Shui wrote:Makes sense. Thanks![...]Referring to a null object is not a problem. Your program crashes ungracefully, but does not corrupt memory. However, in either approach, it can easily end up being a dangling pointer. But to refer to a null location is quite easy: int *foo; // null ptr auto a = x(*foo); assert(&a.xa() == null); Your approach is less desirable because of the closure to point at a given reference which can be had with just a reference. Needless allocation. -Steve
Sep 01 2016