Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
September 01, 2016 Storing a reference | ||||
---|---|---|---|---|
| ||||
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. |
September 01, 2016 Re: Storing a reference | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | 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.
|
September 01, 2016 Re: Storing a reference | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rene Zwanenburg | 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:
>> [...]
>
> 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.
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.
|
September 01, 2016 Re: Storing a reference | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | 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. |
September 01, 2016 Re: Storing a reference | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On 9/1/16 4:38 PM, Yuxuan Shui wrote:
> 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:
>>> [...]
>>
>> 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.
>
> 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.
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
|
September 01, 2016 Re: Storing a reference | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 1 September 2016 at 21:07:36 UTC, Steven Schveighoffer wrote:
> On 9/1/16 4:38 PM, Yuxuan Shui 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.
>
> -Steve
Makes sense. Thanks!
|
Copyright © 1999-2021 by the D Language Foundation