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.
#include <iostream>
usingnamespace 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?
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)
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?