CPSC 427: Object-Oriented Programming
Michael J. Fischer
Reference Types (cont.)
Custom subscripting Suppose you would like to use 1-based arrays instead of C++’s 0-based arrays.
We can define our own subscript function so that sub(a, k) returns the L-value of array element a[k-1].
sub(a,k) can be used on either the left or right side of an assignment statement, just like the built-in subscript operator.
Constant references Constant reference types allow the naming of pure R-values.
const double& pi = 3.1415926535897932384626433832795;
Actually, this is little different from
const double pi = 3.1415926535897932384626433832795;
In both cases, the pure R-value is placed in a read-only object, and pi is bound to its L-value.
A review of definitions
LHS and RHS contexts
Example
int x = 3 creates an object on the stack of type int, stores the
number 3 in it, and gives it the name “x”.
Let 0x1234 be the address of the newly-created object x.
In the expression y = x+1, the name x appears in RHS context.
Its R-value, 3, is fetched from x and used by the + operator.
The name y appears in LHS context.
Its L-value is where the result of x+1 is stored.
Pointers
A pointer is a special kind of R-value that embeds a reference.
The prefix operator *, applied to a pointer, returns the reference
embedded in the pointer. This operation is called following the
pointer.
A pointer that embeds a reference of type T is said to have type
T*.
If x is a reference of type T, then the prefix operator & can be applied to
x to produce a pointer to x.
The type of &x is T*. Thus, *&x is an alias for x.
Pointer objects
Examples Presented in Class
Several examples were presented in class on the blackboard.
Hand-drawn pictures used boxes to represent objects, hex numbers to
represent L-values, numbers inside boxes to represent primitive R-values,
and arrows starting inside one box and pointing to another to represent
pointers.
Anyone who missed class is encouraged to borrow class notes from someone who attended.
Comparison of reference and pointer
Concept summary
Concept | Meaning |
Object | A block of memory and its contents. |
L-value | The machine address of an object. |
R-value | The value stored in an object. |
Pointer | An R-value consisting of a machine address. |
Pointer object | An object into which a pointer can be stored. |
Reference | A typed L-value. |
Identifier | A name which is bound to a reference. |
Type summary
Let T be any type.
Concept | Type | Meaning |
Object | T | L-value has type T&, R-value has type T. |
L-value | T& | The object at its address has type T. |
R-value | T | The type of the data value is T. |
Pointer object | T* | L-value has type T*&, R-value has type T*. |
L-value of ptr obj | T*& | The object at its address has type T*. |
Pointer R-value | T* | The type of the data value is T*. |
Declaration syntax
T x; | Binds x to the L-value of a new object of type T. |
T& x=y; | Binds x to the L-value of y, which has type T&. |
T* x = new T; | Binds x to the L-value of a new pointer object x of type T*, creates a dynamically-allocated object of type T, and stores a pointer to it in x. |
T* y; | Binds y to a new uninitialized object of type T*. |
Storing a list of objects in a data member
A common problem is to store a list of objects of some type T as a data
member li in a class MyClass.
Here are six ways it can be done:
1. | T li[100]; | li is composed in MyClass. |
2. | T* li[100]; | li is composed in MyClass. Constructor does loop to store new T in each array slot. |
3. | T* li; | Constructor does li = new T[100];. |
4. | T** li; | Constructor does li = new T*[100]; then does loop to store new T in each array slot. |
5. | vector<T> li; | Uses Standard vector class. T must be copiable. |
6. | vector<T*> li; | Constructor does loop to store new T into each vector slot. |
How to access
Here’s how to acces element 3 in each case:
1. | T li[100]; | li[3]. |
2. | T* li[100]; | *li[3]. |
3. | T* li; | li[3]. |
4. | T** li; | *li[3]. |
5. | vector<T> li; | li[3]. |
6. | vector<T*> li; | *li[3]. |