I'm trying to understand copy assignment in C++. I know it's best to use copy-and-swap idiom for this operator. But for this simple class without consider the Exception safety, when will *ps = *(h.ps);
fail? could you please provide some examples where this can go wrong? thanks
class HasPtr {
public:
HasPtr(std::string const & s = std::string()):
ps(new std::string(s)), i(0) {}
HasPtr(HasPtr const & h):
ps(new std::string(*(h.ps))), i(h.i) {}
HasPtr & operator = (HasPtr const & h) {
*ps = *(h.ps);
i = h.i;
return *this;
}
~HasPtr(){ delete ps;}
private:
std::string * ps;
int i;
};
I've tried to use GPT, it says there will be a memory leak, but I just can't see it
i = h.i
can't throw, so that is not an issue in this specific case.std::string
. That should simply bestd::string
instead ofstd::string*
and then you don't need any of your copy overloads, destructor ornew
. Follow the rule-of-zero whenever possible. If necessary, because you can't store the object directly by-value for whatever reason, usestd::unique_ptr
, not raw pointers andnew
, to achieve this.new std::string(s)
ehr... no. You will NOT know who owns the pointer. In C++ avoid using "owning raw pointers" at all costs. Use std::unique_ptr or std::shared_ptr depending on the ownership model you need. With your "design" you can easily run into double free issues, you will have to implement your move and copy constructors to do what is right (e.g. move ownership ofps
or share it)*ps = *(h.ps);
fail? Out of Memory exception allocating more storage for*ps
, but since nothing else in the receivingHasPtr
has been changed at that point, no harm is done to it (but only becausestring
itself has a strong exception guarantee). As my fellow anonymous user points out, if you moved thei = h.i;
up a line so thati
could have changed before the exception blew up, that would be a problem. This class is too friendly. To get a better example, where there is a lot of room for fail, write an assignment operator for a roll-your-own linked list class.