Search code examples
c++nullnew-operatorcopy-assignment

Can you create a new instance with the copy assignment operator?


I'm trying to wrap my head around the copy assignment operator in C++, and I'm wondering if there's a way to create a new instance if the object is null.

class Person {
public:
    Person(string name) { pName_ = new string(name); }
    ~Person() { delete pName_; }
    Person(const Person& rhs) {
        if (pName_ != NULL) delete pName_;
        pName_ = new string(*(rhs.pName()));
    }
    Person& operator=(const Person& rhs) {
        cout << "begin copy..." << endl;
        if (this == NULL) {
            Person* p = new Person(rhs);
            cout << "end copy null..." << endl;
            return *p; // Not working?
        }
        delete pName_;
        pName_ = new string(*(rhs.pName()));
        cout << "end copy..." << endl;
        return *this;
    };
    string* pName() const { return pName_; }
    void printName() { cout << *pName_ << endl; }
private:
    string* pName_;
};
int main() {
    Person *a = new Person("Alex");
    Person *b = new Person("Becky");
    Person *c = NULL;
    *b = *a; // copy works
    *c = *a; // copy doesn't
    if (a != NULL) a->printName(); // Alex
    if (a != NULL) delete a;
    if (b != NULL) b->printName(); // Alex
    if (b != NULL) delete b;
    if (c != NULL) c->printName(); // NULL
    if (c != NULL) delete c;
    return 0;
}

This is the output:

begin copy...
end copy...
begin copy...
end copy null...
Alex
Alex

Is there something I can change in my code to make this work, or is this something I shouldn't even attempt to try?


Solution

  • The code you have shown is all kinds of wrong, and needs to be rewritten.

    You are calling an improperly implemented copy assignment operator via a dereferenced NULL pointer, which is undefined behavior. A copy assignment operator is defined to be called only with valid objects, and must copy values from one object to another, and return a reference to the object that was copied to. You are not doing that.

    To answer your question, NO, the copy assignment operator cannot create a new object when this is NULL. For starters, if this is NULL then you have a bug in your code that needs to be fixed. But even if this were NULL, there is no way for the operator to update the caller's pointer (assuming a pointer were used in the first place) to point at a new object instance. this is just a compiler-generated parameter containing the memory address of the object being called into, it is not the caller's original pointer used to invoke the operator. So, if the operator did allocate a new object on the heap, that object will be leaked when the operator exits, as the caller won't have a pointer to the object to free it later.

    A proper version of your code should look more like this instead:

    class Person {
    public:
        Person(const string &name) : pName_(name) {}
    
        Person& operator=(const Person& rhs) {
            // if you remove these output statements then
            // this entire operator can be removed...
            cout << "begin copy..." << endl;
            if (this != &rhs) {
                pName_ = rhs.pName();
                cout << "non self copied..." << endl;
            }
            cout << "end copy..." << endl;
            return *this;
        }
    
        string pName() const {
            return pName_;
        }
    
        void printName() const {
            cout << pName_ << endl;
        }
    
    private:
        string pName_;
    };
    
    int main() {
        Person *a = new Person("Alex");
        Person *b = new Person("Becky");
        Person *c = NULL;
    
        *b = *a;
        //*c = *a; UNDEFINED BEHAVIOR! 
    
        if (a) {
            a->printName();
            delete a;
        }
    
        if (b) {
            b->printName();
            delete b;
        }
    
        if (c) {
            c->printName();
            delete c;
        }
    
        return 0;
    }