Copy constructor doesn't get called but it still has an effect on the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A 
{
public:
	A() { cout << "A's constructor" << endl; }
	~A() { cout << "A's destructor" << endl; }
}; 

class B
{
public:
	operator A() const { return A(); }
};

void f(A q) {}

int main() 
{
	B d1;  
	f(d1);
	return 0;
} 

Here's what I expected the code above to do before I ran it: The call to f results in a call to the conversion function in class B which returns a temporary object. q's constructor gets called and when f exits, q's destructor gets called. I expected the following output:

A's constructor
A's destructor


but the output I got was:

A's constructor
A's destructor
A's destructor


Since there's an extra destructor call in the output, an extra object must have been created somewhere, possibly due to a synthesized copy constructor. I decided to add a copy constructor to A to see if it would get called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;

class A 
{
public:
	A() { cout << "A's constructor" << endl; }	
	A(const A& c) { cout << "A's copy" << endl; }
	~A() { cout << "A's destructor" << endl; }
}; 

class B
{
public:
	operator A() const { return A(); }
};

void f(A q) {}

int main() 
{
	B d1;  
	f(d1);
	return 0;
} 



I ran this new version of the code and got the following output:

A's constructor
A's destructor


As you can see, my copy constructor hasn't been called because "A's copy" doesn't appear in the output. Adding the copy constructor still had an effect on the code though because before it was added, there were two destructor calls in the output and now there's only one. What's going on here?


Last edited on
The compiler changes which optimization it uses depending on whether the object is trivially copy constructible. When you added a non-trivial copy ctor, you changed what the compiler was allowed to do.
when I compiled the code you have written firstly, I got a correct output:
A's constructor
A's destructor


you get a 2nd A's destructor if you create d1 as an object of a class A, not B, because that's when copy constructor is called
void f(A q) {} creates a new A object initialized with already existing object which is send as a parameter - if the parameter is object of A class, then implicit copy constructor is called (it doesn't print any message, but then, at the end of the function f, destructor is called and prints the message)

if the parameter is object of another class, it results in a call of conversion function, where constructor is called (message) and then destructor (message)
Last edited on
It would appear, in the second case an optimization takes place that does not in the first. Since both B::operator A and f are trivial to inline, the code probably ends up looking something like this:

1
2
3
4
5
int main()
{
    B d1 ;
    d1::operator A() ;
}


It seems odd the same optimization isn't used with a defaulted copy constructor. What compiler are you using?

GCC seems to handle it uniformly.
http://ideone.com/3kUCSr
cire, I ran the code you linked to in visual studio 2010 and here's the output:

0030F8A7: A::A()
In f, q's address is 0030F884
0030F884: A::~A()
0030F8A7: A::~A()
0030F884: C::C()
In g, q's address is 0030F884
0030F884: C::~C()

Last edited on
Topic archived. No new replies allowed.