Doubts on C++ copy constructor concept

Hi,

If I run the following program

class A {
public:
    A()  { cout << "default" << endl; }
    A(const A&) { cout << "copy" << endl; }
};

A tmp; 
A fun() {
    return tmp;
}

A test() {
    A tmp;
    cout << &tmp << endl;
    return tmp;
}

int main() {
    A a = fun();
    A b = test();
    cout << &b << endl;
}

I am getting the following output:

default
copy
default
0xbfbe1792
0xbfbe1792

My doubts are:

1) Why 'const' keyword is so necessary (without which compiler is throwing error) here? why it is not optional and why compiler is stressing to add it which is not happening in normal times?

2) Copy constructor is called when an object is returned by value from a function, as it is one of the place where copy constructor should be called. But, why it is not happening during the second object b's creation?

3) In the above code the output shows the same address on the stack for the 2 objects, but the same code in C using structures instead of classes shows a different address. I know local variables (and objects) inside a function are created in the stack and getting destroyed after the function call. Hence, theoretically it should point to different addresses, with a local copy for each one. But, why in C++, it is holding the same address??

It's a sanity check to help guarantee that your copy constructor won't have any weird side-effects. You're passing a reference into it, which is handy since no copy's made -- very bad juju to use a copy constructor inside a copy constructor! -- but they don't want to let you change the original object, just read from it! So they demand a 'const' from you as a sign of good faith. :wink:

Good question. For some reason the scope of the variable seems to change what constructor it uses. Perhaps it's optimizing the extra copy away.

That's really, really weird. Hmmm...

I figured it out! The optimizer noticed that you were never doing anything with the objects and optimized the function call away, pasting it inside your code, like this:

int main() {
    A a = fun();
    A b;
    cout << &b << endl;
    cout << &b << endl;
}

They call that "inlining". g++ seems to do a lot of aggressive inlining by default and nothing I've found actually, really turns it off here, from -O0 up to and including __attribute__ ((noinline)) and the asm("") inline-assembly kludge.

1 Like