Copy Constructor Undefined Call

154 views Asked by At

This is the full example (source book: C++ From Ground Up, 3rd Edition, page 219-320):

class sample {
    char *s;
    public:
        sample(); // normal constructor
        sample(const sample &ob); // copy constructor
        ~sample( ) { cout << "s: " << s <<" ,Freeing s\n"; if(s) delete [] s;}
        void show() { cout << s << "\n"; }
        void set(char *str);
        sample operator=(const sample &ob); // overload assignment
};
// Normal constructor.
sample::sample() {
    s = new char('\0'); // s points to a null string.
    cout << "Normal constructor: s: " << strlen(s) << endl;
}
// Copy constructor.
sample::sample(const sample &ob) {
    cout << "Copy constructor: ob.s: "<< ob.s << " ,strlen(ob.s): " <<  strlen(ob.s) << "\n";
    s = new char[strlen(ob.s)+1];
    strcpy(s, ob.s);
}
// Load a string.
void sample::set(char *str) {
    s = new char[strlen(str)+1];
    strcpy(s, str);
}
// Overload assignment operator.
sample sample::operator=(const sample &ob) {
    /* If the target memory is not large enough
    then allocate new memory. */
    cout << "operator= strlen(ob.s): " << strlen(ob.s) << " ,strlen(s): " << strlen(s) << endl;

    if(strlen(ob.s) > strlen(s)) {
        cout << "operator= Larger memory of target object. Deleting current...\n";
        delete [] s;
        s = new char[strlen(ob.s)+1];
    }
    strcpy(s, ob.s);

    return *this;
}
// Return an object of type sample.
sample input() {
    char instr[80];
    static sample str;
    cout << "Enter a string: ";
    cin >> instr;
    str.set(instr);

    return str;
}

int main() {
    sample ob;
    // assign returned object to ob
    ob=input(); // This is now OK
    ob.show();

    return 0;
}

However I do not get why TWO times copy constructor is called. (output once code is ran)

Normal constructor: s: 
Normal constructor: s: 
Enter a string: Hello
Copy constructor: ob.s: Hello ,strlen(ob.s): 5
operator= strlen(ob.s): 5 strlen(s): 0
operator= Larger memory of target object. Deleting current...
Copy constructor: ob.s: Hello ,strlen(ob.s): 5 
s: Hello, Freeing s
s: Hello, Freeing s
Hello
s: Hello, Freeing s
s: Hello, Freeing s

I know it is called when input() function returns, and create temporary object (by calling copy constructor), but I do not get why second time since, as much as I know (but maybe I am wrong) copy constructors are NOT called for assignment operations, but it looks like, despite of that, when return *this; is called (when overloaded operator returns value), copy constructor is called? What did I missed?

Thankx

1

There are 1 answers

2
Anton Savin On

The code is really terrible. Not to mention other bugs, here is why copy constructor is called twice.

  1. First time it's called when an object is returned from input() since it's static and returned by value, so no RVO can be applied.

  2. The second call happens as a result of return *this; in operator=() because for some reason it's returning an object also by value:

    sample operator=(const sample &ob);
    // ^^^