An important potential change to the language: transitory ref
Steven Schveighoffer
schveiguy at yahoo.com
Fri Mar 19 20:20:59 PDT 2010
On Fri, 19 Mar 2010 22:56:59 -0400, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> Hello,
>
>
> Walter and I are mulling over an idea that may turn out to be extremely
> interesting for D.
>
> Consider the following desideratum: D is a garbage-collected language,
> but we want to be able to define "completely encapsulated" types. That
> means types that never escape pointers to their internal data. If we
> manage to do so, then the type can manage memory any way it desires.
>
> Consider the case of a simple container, e.g. an array. If we manage to
> convince the array to never "leak" a reference to an element, the array
> is free to deallocate memory as it wishes.
>
> One way to achieve that is by simply having the array type return
> rvalues. That is (stylized code below for a type Array!T) instead of:
>
> ref T opIndex(size_t index);
>
> we'd have
>
> T opIndex(size_t index);
>
> and so on. That way nobody can escape a pointer to stuff pointing into
> the array, so the array is safe and can reallocate memory whenever it
> wishes without fearing that someone has squirreled a pointer to its
> buffer.
>
> I'm encouraged that Scott Meyers' Effective C++ topic 'Avoid returning
> "handles" to internal data' talks essentially about that.
>
> Of course, the problem is that you now can't change stuff inside the
> array. Also there is an efficiency issue.
>
> So I was thinking of the following: how about still returning a
> reference, but define a rule in the language that references can't
> escape - you can't take their address and squirrel it away; the only
> thing you can do is use them right on the spot or pass them down to
> functions.
>
> Essentially that means: "I'm giving you the address of the object, but
> in a scoped manner - there's nothing you can do to save it beyond the
> current expression."
>
> To clarify, for an Array!T object, you can do:
>
> arr[5] = obj;
>
> but you can't do:
>
> T* p = & arr[5];
>
> The former uses the reference anonymously right there, and the latter is
> verboten because it could potentially escape "p" outside the current
> expression, and an array resize would leave p dangling.
>
> Are we hamstringing the language in a way that would disable important
> idioms?
What about returning refs that are ref returns or part of other refs? For
example:
ref int foo(ref int x)
{
return x;
}
ref int bar()
{
int x;
return foo(x);
}
The reason I bring this up is because it's exactly what a struct is
doing. Basically, the problem is not so much that you cannot squirrel it
away, but you can return it out of the stack scope it was allocated on. I
don't know if there's a way to fix this without restricting struct members
from returning ref items.
For instance, try to find a rule that prevents the above from compiling,
but allows the following to compile.
struct S
{
private int x;
ref int getX() { return x;}
}
struct T
{
S s;
ref int getSX() { return s.x; }
}
-Steve
More information about the Digitalmars-d
mailing list