简体   繁体   中英

Is copy constructor called when the temporary returning object is assigned to another object immediately

i am having problem understanding how the output of this code comes out like this:

#include<iostream>
using namespace std;

class three_d
{float x,y,z;
public:
    three_d(){x=y=z=0;cout<<"\n\tDefault Constructor";}
    three_d(float a,float b,float c){x=a;y=b;z=c;cout<<"\n\tOverloaded Constructor";}
    three_d(const three_d &obj){x=obj.x;y=obj.y;z=obj.z;cout<<"\n\tCopy Constructor";}
    three_d operator+(three_d op2);
    three_d operator=(three_d op2);
    void show();
    ~three_d(){cout<<"\n\tDestructor Working !!";}
};

three_d three_d::operator+(three_d op2)
{
    x=x+op2.x;
    y=y+op2.y;
    z=z+op2.z;
    return *this; 
}

three_d three_d::operator=(three_d op1)
{
    x=op1.x;
    y=op1.y;
    z=op1.z;
    return *this;
}

void three_d::show()
{
    cout<<"\n\n\tValues are : x="<<x<<" y="<<y<<" and z="<<z<<"\n";
}

int main()
{
    three_d ob1(2.1,2,2.2);
    three_d ob2(1,1,1), ob3;
    ob3=ob1+ob2;
    ob1.show();
    ob2.show();
    ob3.show();

    return 0;
}

The output comes as :

1. Overloaded Constructor 
2. Overloaded Constructor
3. Default Constructor
4. Copy Constructor
5. Copy Constructor
6. Destructor Working !!
7. Copy Constructor
8. Destructor Working !!
9. Destructor Working !!
10. Values are : x=3.1 y=3 and z=3.2
11. Values are : x=1 y=1 and z=1
12. Values are : x=3.1 y=3 and z=3.2
13. Destructor Working !!
14. Destructor Working !!
15. Destructor Working !!

So my questions are:

  • In the 5th line of output what is this copy constructor for? is it for *this pointer (but as it is a pointer i dont think it needs a copy constructor)? The fourth line is for object op2(i suppose) ?
  • If above statement is true when overloading "=" why is only one copy constructor used(when it also have a returning value ?
  • When is the temporary(returning) object destructed ?
  • Please explain how the output is ordered like this.
  • Even if i change the overloaded "+" to something like this :

    three_d three_d::operator+(three_d op2)
    {three_d temp;
    temp.x=x+op2.x;
    temp.y=y+op2.y;
    temp.z=z+op2.z;
    return temp;
    }

the output of copy constructor for "=" remains same(though values will be changed) ie only 1 copy constructor for "=". However I think there must be 2 copy constructors for "=" 1 for op1 object and other for *this .

If i use simple assignment in main like :
ob3=ob1;
the copy constructor is called twice as expected.
Please explain.

Best way to understand the statement, i think you should see it as;

ob3.operator=(ob1.operator+(ob2));

4. Copy Constructor : this is creating a temporary object from ob2 because you calling operator+ by value. Lets call this temporary tmp2 .

5. Copy Constructor : this is creating a temporary object from ob1 becasue you are returning from operator+ by value.Lets call this temporary tmp1 .

6. Destructor Working !! : when operator+ finishes, temporary object tmp2 destructed.

-->Important note here : VC++ and GCC compilers interestingly passes temporary object tmp1 returned from operator+ to operator= by reference even operator= takes input by value(copy). this is why you dont see another copy constructor here. [This needs explanation by an expert]

7. Copy Constructor : this is creating another temporary from ob3 because you return from operator= by value. Lets call this last temporary tmp3 .

8. Destructor Working !! : when operator+ finishes, tmp1 is destructed.

9. Destructor Working !! : when operator+ finishes, tmp3 is destructed at the end of the assignment.

When i see the result from GCC compiler, it is as following:

4.Copy Constructor
5.Copy Constructor
6.Copy Constructor
7.Destructor Working !!
8.Destructor Working !!
9.Destructor Working !!

And similar analysis that i have done as follows:

  1. tmp2 creation
  2. tmp1 creation
  3. tmp3 creation
  4. tmp3 destruction
  5. tmp1 destruction
  6. tmp2 destruction

Note: We are assuming you know the true way of defining operator+ and operator= with signatures.(one is friend function taking two constant paramers, other returning by reference etc.)

Both of your operator+ and operator= return objects. They are copies of *this . Hence, the calls to the copy constructor.

If would like to avoid the call to the copy constructor, in order to avoid the cost of a copy, change those function to return a reference.

three_d const& three_d::operator+(three_d op2)
{
   x=x+op2.x;
   y=y+op2.y;
   z=z+op2.z;
   return *this; 
}

three_d const& three_d::operator=(three_d op1)
{
   x=op1.x;
   y=op1.y;
   z=op1.z;
   return *this;
}

PS

Your operator+ function modifies the LHS of the operand. That is uncommon. In an expression

a = b + c;

you don't expect b to be changed. This is something to think about.

If you want to implement those functions in a well behaving way, you should change them to:

three_d three_d::operator+(three_d const& rhs) const
{
   three_d r(*this);
   r.x += rhs.x;
   r.y += rhs.y;
   r.z += rhs.z;
   return r; 
}

three_d& three_d::operator=(three_d const& rhs)
{
   if ( this != &rhs )
   {
      x = rhs.x;
      y = rhs.y;
      z = rhs.z;
   }
   return *this;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM