The dereference (*
) and arrow (->
) operators are often used in classes that represent iterators and in smart pointer classes (§ 12.1, p. 450). We can logically add these operators to our StrBlobPtr
class as well:
class StrBlobPtr {
public:
std::string& operator*() const
{ auto p = check(curr, "dereference past end");
return (*p)[curr]; // (*p) is the vector to which this object points
}
std::string* operator->() const
{ // delegate the real work to the dereference operator
return & this->operator*();
}
// other members as before
};
The dereference operator checks that curr
is still in range and, if so, returns a reference to the element denoted by curr
. The arrow operator avoids doing any work of its own by calling the dereference operator and returning the address of the element returned by that operator.
Operator arrow must be a member. The dereference operator is not required to be a member but usually should be a member as well.
It is worth noting that we’ve defined these operators as const
members. Unlike the increment and decrment operators, fetching an element doesn’t change the state of a StrBlobPtr
. Also note that these operators return a reference or pointer to nonconst string
. They do so because we know that a StrBlobPtr
can only be bound to a nonconst StrBlob
(§ 12.1.6, p. 474).
We can use these operators the same way that we’ve used the corresponding operations on pointers or vector
iterators:
StrBlob a1 = {"hi", "bye", "now"};
StrBlobPtr p(a1); // p points to the vector inside a1
*p = "okay"; // assigns to the first element in a1
cout << p->size() << endl; // prints 4, the size of the first element in a1
cout << (*p).size() << endl; // equivalent to p->size()