Heron References
Heron reference types are a cross between C style pointers and C++ references. A reference is a handle
to a value, which can be shared without copying the value. A variable is also a handle for a value, but copying
a variable results in the copying of the value it represents.
In Heron there are several different kinds of references, that represent different kinds of concerns. The two principal kinds of references
are strong references which are denoted by a caret or hat symbol ( ^ ) and the weak references which are denoted by an ampersand ( & ). Other
references are the result of specific operations and exist primarily for typecasting.
Strong References
A strong reference represents a deletable handle to a dynamically allocated object. When dynamically allocating an object it must
be passed to a strong reference, a failure to do so causes a compile-time error. The delete operation may also only ever
be applied to strong references. It can be said that a strong reference indicates ownership of an object, and that ownership can be shared
with other strong references.
New References
The result of a new operation is actually a new-reference which is a separate kind of reference type. A new-reference
is only used for being assigned to a strong reference, and supports no other operations.
Weak References
The more common reference in code, is the weak reference. The weak reference can be assigned from a strong reference, or from the
result of an address-of operation. A weak reference does not represent any kind of ownership of the object, and can not be deleted.
This reflects the reality that the majority of time, in any code that uses pointers, it is inappropriate to allow explicit
deletion of pointers.
Address References
The result of the address-of operation ( @ ) is an address reference. An address reference can only be assigned
to a weak reference for the obvious reason that deletion of a value object is a clear error. This kind of error detection
is not possible in a single pointer/reference system such is found in C++
References Example
Here is a code snippet which demonstrates how references can and can't be used:
MyObject obj;
MyObject^ strong_ref;
MyObject& weak_ref;
weak_ref = new MyObject; // compiler error: can't assign a new-reference to a weak-references
strong_ref = new MyObject;
strong_ref = @value; // compiler error: can't assign an address-reference to a strong-reference
weak_ref = @value;
delete strong_ref;
delete weak_ref; // compiler error: can't delete weak references
Reference Assignment Table
The following table shows which references can be assigned to which references. The top line is the rvalue ( right hand side
of an assignment statement )
| strong | weak | address | new |
| strong |
yes |
no |
no |
yes |
| weak |
yes |
yes |
yes |
no |
Reference Differentiation Motivation
The reason for the differentiation into strong and weak references
is to make explicit ownership semantics. In other words, it is important to identify which
references may or may not delete a dynamically allocated object. Traditionally languages with pointers such as C++ and Pascal
represents dynamic objects using raw pointers. A raw pointer does not indicate whether that reference is expected to delete or not
the value being referenced. This can lead to numerous errors, and requires extra code commenting. It is preferable to have
programmer intention explicit within the code. It reduces the possibility of error, and the need for commenting.
Garbage Collection
Clearly Heron has no pre-defined notion of a garbage collector. A Heron implementation can easily choose to provide a
garbage collection mechanism. It doesn't conflict with any part of the language, except for one fact: the delete should still
remain valid as an indication of programmer intention to no longer use an object, and to trigger a destructor. In the case of
a premature call to delete during a non-GC implementation it would eventually result in an error when the object is accessed
again later. It would be a good idea for a GC implementation to throw an error earlier, because a GC can triviallly
determine that the object is still live. Premature deletion, indicates a specification conflict on behalf of a programmer.
It was important for Heron to allow low-level implementation which don't require a garbage collection mechanism,
because it is more appropriate to do manual resource allocation for certain classes of programs.
|