In the book of "The C++ Programming Language", the author gave the following example along with several statements:
Defining an operator, such as [], to be used for both reading and writing is difficult where it is not acceptable simply to return a reference and let the user decide what to do with it.
Cref, is to help implement a subscript operator that distinguishes between reading and writing.
Why [] is difficult to be defined when to be used for both reading and writing?
How does the definition of class Cref help to solve this issue?
class String{
struct Srep;
Srep *rep;
public:
class Cref;
// some definitions here
void check (int i) const { if (i<0 || rep->sz<=i) throw Range( );}
char read( int i) const {return rep->s[i];}
void write(int i, char c){ rep=rep->get_own_copy(); rep->s[i]=c;}
Cref operator[] (int i){ check(i); return Cref(*this, i);}
char operator[] (int i) const{check(i); return rep->s{i];}
}
class String::Cref{
friend class String;
String& s;
int i;
Cref(String& ss, int ii): s(ss),i(ii) {}
public:
operator char( ) { return s.read(i);}
void operator=(char c){s.write(i,c);}
};
If you don’t define a class
Crefthat solves this issue, then you have to do whatstd::mapdoes:This returns a reference, which must be backed by a valid memory location, and therefore
The assertion will succeed (meaning,
"foo"is now a valid key in the map) even though you never assigned something tom["foo"].This counterintuitive behavior can be fixed by the
Crefclass in your example — it can perform the appropriate logic to createm["foo"]only when you assign to the reference, and ensure thatm.find("foo") == m.end()if you didn’t perform some assignment when you tried to read the nonexistantm["foo"].Likewise, in your
Stringclass (which is a reference-counted string — strings share their string data, and a new copy is created when you change a string whose data is shared with another string), you’d have to make a copy when usingoperator[]to read characters. The use of theCrefclass, allows you to ensure that you only make a copy when usingoperator[]to write.