Below is an exercise from C++ Primer 5th Edition:
Exercise 13.22: Assume that we want HasPtr to behave like a value. That is, each object should have its own copy of the string to which the objects point. We’ll show the definitions of the copy-control members in the next section. However, you already know everything you need to know to implement these members. Write the HasPtr copy constructor and copy-assignment operator before reading on.(Page 511)
Codes for Class HasPtr
:
class HasPtr
{
public:
//! default constructor
HasPtr(const std::string &s = std::string()):
ps(new std::string(s)), i(0) { }
//! copy constructor
HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
HasPtr&
operator = (const HasPtr& hp);
~HasPtr()
{
delete ps;
}
private:
std::string *ps;
int i;
};
My code for this copy-assignment operator:
HasPtr&
HasPtr::operator = (const HasPtr &hp)
{
delete ps;
ps = new std::string(*hp.ps);
i = hp.i;
return *this;
}
Codes presented in the following section from this book:
HasPtr&
HasPtr::operator = (const HasPtr &rhs)
{
auto newp = new string(*rhs.ps); // copy the underlying string
delete ps; // free the old memory
ps = newp; // copy data from rhs into this object
i = rhs.i;
return *this; // return this object
}
By executing step by step, I found a slight difference between the two codes. In my code it doesn't change the address to which ps
points, whereas the code from the book makes ps
point to a new address. I'm wondering whether this subtle difference has any significant meaning? Should I always change the pointer to a new address in similar situations? why?
Your code has a problem with self-assignment and with exceptions: assume that the memory allocation throws a
std::bad_alloc
exception. When coding, you should always assume that memory allocations can go wrong although the actually rarely do. In the codeps
would point to stale member when the second line of code throws an exception. Incidentally, if you end up self-assigning the object, you actuallydelete
the memory of the only before accessing it. Thus, it is a good idea to first copy the content of the right hand side, then put things into place, and finally release resource.As it happens, these are exactly the operations of
swap()
operation you generally want for any type holding resourcesThe way to leverage these three operation is known as copy and swap idiom: