class X {
public:
   X () : myID(id) {}
   X (const X& right) : myID(++id) {}
   friend ostream& operator<< (ostream&, const X&);
private:
   static int id;
   int myID;
};

int X::id = 0;

ostream& operator<< (ostream& os, const X& x) {
   return os<<x.myID;
}

X f (X x1, X& x2) {
   x1 = x2;
   return x2;
}
void main () {
   X x1, x2 = x1;
   X x3 = f(x1,x2);
   cout<<x1<<','<<x2<<','<<x3;
}

What I don't understand is how the 23. line of program works (3rd line of main() function). I know that it should use a copy constructor, and it does it at first,but after finishing copy constructor function it calls the f function and after that initializes x3 with the returned value of function f. Why does it call function f at all after copy constructor? Isn't it supposed to call only copy constructor?
What i'm trying to say is that I don't understand how copy constructor works when I have a function on the right side... Please help.

Recommended Answers

All 3 Replies

Tracer bullets are always useful in a case like this. Consider the following updates:

X (const X& right) : myID(++id) {cerr << "Copied " << id - 1 << endl;}

and

X f (X x1, X& x2) {
   cerr << "Enter f" << endl;
   x1 = x2;
   cerr << "Exit f" << endl;
}

You'll notice that there is a copy constructor called twice before you enter the body of the function f. Since the first argument to f is not a pointer or reference you pass in a copy of x1 thus invoking the copy constructor.

stankefa,

Welcome to DaniWeb!

Try commenting line 23 and 24. You should see only the copy constructor called. On line 23, you are calling f(), so of course it will be called!

Also, in the future, please use a descriptive thread title - for this question maybe something like "Copy constructor problem".

David

You have 3 different instances where the copy constructor is used and 1 instance where you've used the compiler-provided assignment operator. To simplify the code a little and make it easier to read, Let's expand your main() (which by the way, regardless of program size, should have an int return not a void return) so that each declaration is on a different line:

int main () {
  X x1
  X x2 = x1;
  X x3 = f(x1,x2);
  cout<<x1<<','<<x2<<','<<x3;
  return 0;
}

Discussion:
The declaration of "x1" uses the default constructor, plain and simple, nothing to discuss here.

The declarations of "x2" and "x3" are both implicit calls to the copy constructor. These declarations account for 2/3 of the uses of the copy constructor. The third use of the copy constructor is when you call f() as part of the declaration of "x3".

The first argument to f() is a pass by value instead of a pass by reference. When you pass an argument to a function by value, a copy of the argument is made and put in the memory assigned to the matching parameter. When f() completes its work and returns, the return value is a temporary variable of type X. Since this is part of the declaration statement for "x3" the copy constructor is now called with the returned temporary as the argument. (If it were not part of the declaration statement, and performed later, it would be an assignment statement.)

commented: It deeply explains how program works. +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.