Umut Tabak
Umut Tabak

Reputation: 1942

temporary and copy constructor

With the below program, I tried to experiment with the copy ctor, there is one point which is not clear, when function f( ) returns it should use the copy-ctor to create a new object for h2, however I guess that is accomplished by the temporary object which uses the constructer of the object and then makes the copy however the destruction output shows that I am wrong on this reasoning... some clarification is appreciated on this problem ;)

#include <fstream>
#include <string>
using namespace std;
ofstream out("HowMany2.out");

class HowMany2 {
  string name; // Object identifier
  static int objectCount;
public:
  HowMany2(const string& id = "") : name(id) {
    ++objectCount;
    print("HowMany2()");
  }
  ~HowMany2() {
    --objectCount;
    print("~HowMany2()");
  }
  // The copy-constructor:
  HowMany2(const HowMany2& h) : name(h.name) {
    name += " copy";
    ++objectCount;
    print("HowMany2(const HowMany2&)");
  }
  void print(const string& msg = "") const {
    if(msg.size() != 0) 
      out << msg << endl;
    out << '\t' << name << ": "
        << "objectCount = "
        << objectCount << endl;
  }
};

int HowMany2::objectCount = 0;

// Pass and return BY VALUE:
HowMany2 f(HowMany2 x) {
  x.print("x argument inside f()");
  out << "Returning from f()" << endl;
  return x;
}

int main() {
  HowMany2 h("h");
  out << "Entering f()" << endl;
  HowMany2 h2 = f(h);
} 

Output

HowMany2()
  h: objectCount = 1
Entering f()
HowMany2(const HowMany2&)
  h copy: objectCount = 2
x argument inside f()
  h copy: objectCount = 2
Returning from f()
HowMany2(const HowMany2&)
  h copy copy: objectCount = 3
~HowMany2()
  h copy: objectCount = 2  // Confused here !!!! why not h copy copy
~HowMany2()
  h copy copy: objectCount = 1
~HowMany2()
  h: objectCount = 0

Upvotes: 2

Views: 366

Answers (3)

Yakov Galka
Yakov Galka

Reputation: 72469

h copy copy is basically h2 from this line:

HowMany2 h2 = f(h);

It's destructed when you exit from main.

h copy is the argument of f, it's destructed when f is returning. Since f returns before main, h copy is destructed before h copy copy.

Note that RVO (return value optimization) was done by the compiler. There are no temporaries created in this code. Actually this code may output different results depending on the compiler. The compiler is free to do 1 or 2 invocations of the copy constructor in this code. (Maybe zero is also possible in this case, I don't know how to justify it though.)

Edit: Your code is implemented by the compiler like this (pseudo-code):

void f(HowMany2 *result, HowMany2* xptr) {
  HowMany2 x(*xptr); // local copy

  x.print("x argument inside f()");
  out << "Returning from f()" << endl;

  new(result) HowMany2(x); // copy the return value

  x.~HowMany(); // destroy local copy
}

int main() {
  HowMany2 h("h");
  out << "Entering f()" << endl;
  HowMany2 h2; // not initialized
  f(&h2, &h);
  h2.~HowMany2();
} 

Upvotes: 2

Loki Astari
Loki Astari

Reputation: 264381

The return value from f() is doing a copy construction back to main.
The result puts the value into the variable h2.

Thus the parameter x in the function is destroyed first (as it leaves the function).
Then h2 then h as the main function exits and its local variables are destroyed.

~HowMany2()
  h copy: objectCount = 2          // destruction of x
~HowMany2()
  h copy copy: objectCount = 1     // destruction of h2
~HowMany2()
  h: objectCount = 0               // festruction of h

If you want to get really freaked out. Turn the optimizations to full -O3 on gcc or build in release mode in VisStudio. See how the output differs.

Upvotes: 0

Flinsch
Flinsch

Reputation: 4341

At that "confusion" point, the temporary local object of function f is destroyed ("h copy"), after it has been returned to create the copy outside the function ("h copy copy"). Then, the objects outside the function are destroyed in reversed order of their creation: the copied object ("h copy copy") and, finally, the original object ("h").

Upvotes: 1

Related Questions