One copy constructor issue that is baffling me

In the following code, I do not understand why isn't the copy constructor called for "ob3" in main and why isn't the destructor called for "temp" in overloaded operator function:

output is:
In the constructor with arguments 10 20
In the constructor with arguments 5 30
10 20
5 30
In copy constructor
In operator before temp
In the constructor with arguments 0 0
In operator after temp
In Destructor 5 30
15 50
In Destructor 15 50
In Destructor 5 30
In Destructor 10 20

~~~~~~~~~~~~~~~

Code is :
~~~~~~~~~~~~
#include <iostream>

using namespace std;

class loc {
int longitude, latitude;
public:

loc(int lg, int lt) {

longitude = lg;
latitude = lt;
cout << "In the constructor with arguments " << longitude <<" " << latitude << endl;
}

~loc () {

cout << " In Destructor " << longitude << " " <<latitude << endl;

}

void show() {
cout << longitude << " ";
cout << latitude << "\n";
}

loc operator+(loc op2);

loc(const loc &ref) {

cout << "In copy constructor" << endl;
longitude = ref.longitude;
latitude = ref.latitude;

}
};

// Overload + for loc.
loc loc::operator+(loc op2)
{
cout << "In operator before temp" << endl;
loc temp(0,0);
cout << "In operator after temp" << endl;
temp.longitude = op2.longitude + longitude;
temp.latitude = op2.latitude + latitude;
return temp;
}
int main()
{
loc ob1(10, 20), ob2( 5, 30);
ob1.show(); // displays 10 20
ob2.show(); // displays 5 30
loc ob3 = (ob1 + ob2);
ob3.show(); // displays 15 50


return 0;
}

loc ob3 = (ob1 + ob2); //this is assignment NOT copy copy constructing - does not use copy constructor - uses assignment operator
Last edited on
Thanks for your response.

But you see ob3 did not exist before that statement was written. SO it is initialization for ob3 and so shouldn't copy constructor be called , because it is always called for initialization...isn't it.

Another thing , if I replace the statement

loc ob3 = (ob1 + ob2);

by

loc ob3 = ob1;

then copy constructor is called !

Whats the difference ? In both cases we are initializing a newly constructed object ob3 !
Then why the difference in behavior ?
Ankur
In C++, there is a thing called (if I remember the term correctly) Conversion by constructor where a statement like loc ob3 = ob1; is treated the same as loc obj3(obj1). (Note this applies only to constructors taking 1 parameter)

So if you have a class like this
1
2
3
4
class myX
{
      myX (int a) {} //constructor taking  1 parameter
};


you can say MyX x1 = 3 and the compiler will implicitly use the myX (int a) constructor.
This implicit conversion can be confusing sometimes because it looks like you are assigning n
integer to a class. If you don't want this implicit conversion to take place, then you can use
the explicit keyword on the constructor.
1
2
3
4
class myX
{
      explicit myX (int a) {} //constructor taking  1 parameter
};


So now MyX x1 = 3 will give an error.

I'm trying to find a link to some documents that have a better explaination
Last edited on
Yes I understand your point. You are right.

But in my case I still don't understand why copy constructor is not called for

loc ob3 = (ob1 + ob2);

You see ob1+ob2 is returning an object and ob3 is being initialized with that object. This is not different than using just one object for initialization as loc ob3 = ob1;

And copy constructor is always called when a non existing object is initialized using another object. But my case differs some how and I don't understand how ?
Can you double check that it is definitely not called??
Yes , it is definitely not called for op3.

In the output I have posted in the very first post, copy constructor is called only once and that is when op2 in the operator function is getting initialized.
This is all "to my knowledge" and I might not be 100% right on this... but this is the way I understand it:

But in my case I still don't understand why copy constructor is not called for

loc ob3 = (ob1 + ob2);


You're not explicitly calling the copy ctor there. Therefore the compiler is free to make optimizations where it deems appropriate (this is a good thing!)

Here, instead of a temporary object being created, copied, then destroyed, it just treats 'ob3' as the temporary object so a copy isn't needed, and thus it doesn't need to be destroyed. This removes a lot of unnecessary code, and the end result is the same.



If you want to bypass the optimization and force the copy ctor, I believe you can do it explicitly with this:


1
2
// just tried it -- this doesn't work
loc ob3 = loc( ob1 + ob2 ); // explicitly using the copy ctor here, so it must be called 



EDIT: I just tried by idea of explicitly calling the copy ctor and it doesn't work. *shrug*

Don't know how to bypass the optimization then. But then again I don't see why you'd ever want to.
Last edited on
In that case, it is probably a compiler thing.
I tried it with both mingw and MSVC and get two slightly different outputs.

MINGW (using GCC) In the constructor with arguments 10 20
In the constructor with arguments 5 30
10 20
5 30
In copy constructor
In operator before temp
In the constructor with arguments 0 0
In operator after temp
In Destructor 5 30
15 50
In Destructor 15 50
In Destructor 5 30
In Destructor 10 20


MSVC In the constructor with arguments 10 20
In the constructor with arguments 5 30
10 20
5 30
In copy constructor
In operator before temp
In the constructor with arguments 0 0
In operator after temp
In copy constructor
In Destructor 15 50
In Destructor 5 30
15 50


Last edited on
Actually, this sort of thing is why I test things in more than one compiler if possible.
This is very interesting !

guestgulkan, is that the complete output from MSVC ?

I think three objects must be destroyed at the end.

Disch, I tried calling the copy constructor explicitly using

loc ob3 = loc(ob1 + ob2);

but it still did not call it.

I am on g++

gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-47)

It could be a compiler thing.

Now that we are on it, consider this:

If I comment out the
return temp;

in operator function, then ob3 still gets some garbage values.

But, why should that happen ? You see ob3 was never constructed in the first place, two reasons: There is no , no argument constructor for the class. Second , there was no return value. So if ob3 never got a chance to be constructed , there is no memory allocated to that object. Then why print garbage values ? I feel this should be a compile time error. In java it would be a compile time error.
The full msvc output looks like this:
In the constructor with arguments 10 20
In the constructor with arguments 5 30
10 20
5 30
In copy constructor
In operator before temp
In the constructor with arguments 0 0
In operator after temp
In copy constructor
In Destructor 15 50
In Destructor 5 30
15 50
In Destructor 15 50
In Destructor 5 30
In Destructor 10 20


great ! Notice how copy constructor is called for ob3 before temp gets destroyed !

And then all three objects ob1, ob2, ob3 are getting destroyed in main.

Thanks a lot,
~C
Topic archived. No new replies allowed.