char& String::operator[](int index) is a bit of a mess.
Reference counting works in two parts. First, there's the actual object that you want to reference count. That's wrapped in a class that has the count and provides methods for checking and changing the count. Secondly, there's the wrapper that clients use. These are created/copied/deleted with abandon, but underneath, it changes count of the wrapped object. When the reference count drops to zero, it releases the wrapped object. So the two work in tandem.
Your problem is two fold. First, your trace code is calling "reference" after it has been deleted in ~RCSmartPointer(). But more importantly, char& String::operator[](int index) is bad.
char& String::operator[](int index) returns a reference to the string. So the underlying string has to be locked down before a reference to it can be given out. The lock down process removes the "shared" flag. And if it was shared, it creates a new instance.
Rather than creating the wrapped object, the code should create a wrapper object. Because it's creating the wrapped, the reference count isn't incremented on creation, so it's deleted in the assignment before can be used, then the actual use attempts to use a deleted object.
The corrected code is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
template<class T>
RCSmartPointer<T>& RCSmartPointer<T>::operator=(const RCSmartPointer& rhs)
{
if (pRC == rhs.pRC)
return *this;
if (pRC)
{
pRC->removeRef();
}
rhs.pRC->addRef();
pRC = rhs.pRC;
return *this;
}
char& String::operator[](int index)
{
if (rcString->isShared())
{
rcString = RCSmartPointer<countedString>(new countedString(rcString->cString));
rcString->markNotShareable();
}
return rcString->cString[index];
}
|