0
#include <iostream>
using namespace std;

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 to do before I ran it: The call to f results in a call to the converter 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 another destructor, an extra object must have been created somewhere. Can someone explain what's happening here?

Karlsson
  • 25
  • 4
  • 3
    Since you are doing a lot of copy-construction, you have to trace copy-constructor calls as well. Why aren't you doing that? In fact, you are creating so many copies, that observing only two objects is surely a consequence of optimization. Technically you should have at least four, if not five. – AnT stands with Russia Jan 18 '14 at 19:30

4 Answers4

1

Use this as your class A:

class A 
{
public:
    A() { cout << "A's constructor: " << this << endl; }
    A(const A& a) { cout << "A's copy constructor: " <<this << " form " << &a << endl; }
    A(A&& a) { cout << "A's move constructor: " <<this << " form " << &a   << endl; }
    A& operator=(const A& a) { cout << "A's assignment" <<this << " form " << &a  << endl; }
    ~A() { cout << "A's destructor: "<< this << endl; }
}; 

And you'll see why.

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
  • When I run your code as is I get the output: A's constructor: 0018F8D4 A's destructor: 0018F8D4. If I uncomment the copy constructor from your code, I get the output: A's constructor: 002CFA5B A's destructor: 002CFA38 A's destructor: 002CFA5B – Karlsson Jan 18 '14 at 21:31
  • @Karlsson: uncomment from my code ??? I cannot understand what you did – Emilio Garavaglia Jan 19 '14 at 09:26
0

There's potential for there to be 3 A objects constructed here. First is the temporary object created by A() in the conversion operator. Then, since the return type of the conversion operator is A, that temporary is copied into the return value. Then the return value of the conversion is copied into the parameter q of f.

To copy an object, the copy constructor is invoked. The default constructor will not be invoked, so you won't see the "A's constructor" message being printed.

It just so happens that the compiler elides one of these copies so that you only actually have one copy occur. Which one is being elided, I can't tell you (but it's probably the copy into the return value).

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
0

I think first destructor call for temporary object and second destructor for object which is constructed by move semantic.

Igor
  • 1,029
  • 9
  • 21
0

The question has been asked many times before, but since it is so generic it is difficult to find the older posts.

You are passing your objects around by value, meaning that the copies are created by copy constructor. Copy constructor is what created that "extra object" in your case. Meanwhile, you do not output anything from the copy constructor and therefore don't see the calls.

You have to add a debug output to your copy-constructor as well. That way you will see what is actually constructed and when.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • I added a copy constructor to class a like you suggested and now one of the destructor calls doesn't appear in the output. What's weird is that the output from the copy constructor doesn't appear either. In other words: when I add the copy constructor, the outpout becomes: A's constructor A's destructor but the text I'm printing within the copy constructor isn't displayed. – Karlsson Jan 18 '14 at 20:21