#include <RCBase.h>
Inheritance diagram for RCBase< Type >:
Public Member Functions | |
virtual Type | read (const int i) const=0 |
virtual void | write (const int i, const Type v)=0 |
These array objects implement copy-on-write semantics.
This abstract class defines two pure virtual functions, read and write and the local ValRef class. The ValRef class is returned for referenced array elements. This class is a proxy which avoids copy-on-read.
An object that implements copy-on-write arrays defines the [] operator (the index operator). The index operator can be used on either the right or left hand size of an assignment. For example, in the statements below a is an instance of an object that implements the index operator.
MyObj b = a; // b is a reference to a MyType v = a[i]; // A right-hand-side reference a[j] = v; // A left-hand-size referenceReferences counted objects share a reference to common data until an object is modified. The copy-on-write semantics means that a unique copy will be made before shared object is modified. Ideally this saves memory and improves performance.
In the example above a and b share a reference to the same data set. When a is read, there should be no effect (other than the read). However, when a is modified (by being written), a unique copy is made first. Although previously a and b referenced the same data, the write operation will force the creation of a unique copy for a and only a will be modified. The b object will retain its previous value.
In a better world there would be some way that the programmer could indicate to the C++ compiler that a particular operator [] function implements the right-hand-side or the left-hand-size semantics.
The naive implementation (which I used in the first two versions of a String class) turns out to be wrong. Here is the slightly simplified code from this somewhat incorrect String class. My intention was that the operator [] function below labeled "LHS" would implement copy-on-write. The operator [] labeled RHS would do a read and nothing more.
This code does not properly implement copy-on-write
// // operator [] (RHS) with an integer index // inline char String::operator [](const int ix) const { return pShare->str[ix]; }
// // operator[] (LHS), integer index // inline char & String::operator [](const int ix) { makeUnique(); // make a unique copy of the shared data return pShare->str[ix]; } // operator []As it turned out, the function labeled LHS is called in most cases, whether the operator [] is on the left or right hand side of the expression. This results in copy-on-read which is, obviously, not desirable and destroys much of the utility for a reference counted object.
The proper implementation of the String object uses an instance of the ValRef object (instantiated for
char
).
inline String::ValRef String::operator[](const int ix) { return ValRef( *this, ix ); }The ValRef object is losely modeled after the Cref class in The C++ Programming Language, Third Edition by Bjarne Stroustrup, Section 11.12.
Definition at line 112 of file RCBase.h.
|
Implemented in RCArray< T >, RCArray< double >, and RCArray< char >. Referenced by RCBase< Type >::ValRef::operator Type(). |
|
Implemented in RCArray< T >, RCArray< double >, and RCArray< char >. Referenced by RCBase< Type >::ValRef::operator=(). |