How can I handle any exception that happens during the allocation memory with new
?
A try{} catch(){}
should be used to catch exceptions thrown during allocation and object creation.
How can I restore the value of buff
to old values incase of exception?
The key here is not really to restore the old values if an exception is thrown, but to first allocate and copy the contents, swapping pointers etc. and then delete the old object and memory. In this way if an exception is thrown, the current contents are left unchanged.
First allocate the memory to a temporary pointer, copy the data required, then swap the new pointer for the old one and delete the old data; akin to the copy-swap idiom. GotW (#59) also has a nice article on this here.
myString& operator= ( const myString& other )
{
if( this != &other ){
try {
char* temp_buff = other.length ? new char[other.length] : nullptr;
// I assume my_strncpy handle NULL pointers etc.
// If not, call it behind an if check for length and pointer validity
my_strncpy( temp_buff, other.buff, length );
std::swap(temp_buff, buff);
delete [] temp_buff;
length = other.length;
}
catch (std::bad_alloc& e) {
// deal with the bad_alloc...
}
catch (std::exception& e) {
// deal with the exception
}
}
return *this;
}
In general, out of memory conditions are significant, so just catching the exception may not always be ideal - it needs to be dealt with by the application as a whole, possibly even by the user for the entire system. A question to ask yourself is; what are you going to do with the exception, how are you going to recover from it?
A more general solution (I assume you really are focused on implementing the operator=
in the current form) is to use a full blown copy-swap implementation.
class myString {
char* buff;
std::size_t length;
// ...
};
myString::myString(myString const& src) :
buff(src.length ? new char[src.length] : nullptr),
length(src.length)
{
if (length)
std::copy(src.buff, src.buff + length, buff);
}
myString::~myString()
{
delete [] buff;
length = 0;
}
void myString::swap(myString& rhs)
{
std::swap(rhs.buff, this->buff);
std::swap(rhs.length, this->length);
}
myString& myString::operator=(myString const& rhs)
{
if (this != &rhs) {
myString temp(rhs);
swap(temp);
}
return *this;
}
// the rest of the class implementation
//... non-member swap for addition utility
inline void swap(myString& lhs, myString& rhs)
{
lhs.swap(rhs);
}