Home > database >  Constructer Calling order
Constructer Calling order

Time:06-09

I know when a constructer is being called, then it gets created in the memory, and when it gets out of the block it gets destroyed unless if it's static.

Know I have this code:

    #include <iostream>
#include <string>
using namespace std;


class CreateSample
{
private:
    int id;
public:
    CreateSample(int i)
    {
        id = i;
        cout << "Object " << id << " is created" << endl;
    }

    ~CreateSample()
    {
        cout << "Object " << id << " is destroyed" << endl;
}
};


void fuct()
{
    CreateSample o1(1);
    static CreateSample o2(2);
}

CreateSample o3(3);
void fuct2(CreateSample o);

int main()
{
    fuct();
    static CreateSample o4(4);
    CreateSample o5(5);
    fuct2(o5);
    return 0;
}

void fuct2(CreateSample o)
{
    CreateSample o6 = o;
}

and my conceren is in object 5, why it's getting called once and gets destroyed 3 times?

CodePudding user response:

CreateSample o5(5); calls the constructor CreateSample(int). fuct2(o5); and CreateSample o6 = o; call the implicitly-defined default copy constructor CreateSample(CreateSample const&). All three of these variables (o6, o, and o5) call the destructor ~CreateSample() when their scope is exited.

The fix is to follow the rule of three and also define a copy constructor and copy-assignment operator:

class CreateSample
{
// ...
    CreateSample(CreateSample const& o) {
        id = o.id;
        cout << "Object " << id << " is copy-constructed" << endl;
    }
    
    CreateSample& operator=(CreateSample const& o) {
        cout << "Object " << id << " is copy-assigned from " << o.id << endl;
        id = o.id;
        return *this;
    }
}

Demo on Compiler Explorer

CodePudding user response:

When you wrote fuct2(o5); you're calling the function fuct2 and passing the argument by value. This means a copy of the argument will be passed to the function using the implicitly defined copy constructor. Thus you get the 2nd destructor call corresponding this object o.

Moreover, in fuct2 you have CreateSample o6 = o; which will also use the implicitly defined copy constructor to create o6. Thus you will get a third call to the destructor corresponding to this o6.


You can confirm this for yourself by adding a copy ctor as shown below:

class CreateSample
{
//other code here
public:
    
    CreateSample(const CreateSample&obj): id(obj.id)
    {
        std::cout<<"Copy ctor called"<<std::endl;
    }
};

And the output you will get is:

Object 5 is created            <------ctor called for o5
Copy ctor called               <------copy ctor called for parameter o
Copy ctor called               <------copy ctor called for object o6
Object 5 is destroyed          <------destructor called for o6
Object 5 is destroyed          <------destructor called for o
Object 5 is destroyed          <------destructor called for o5

Demo


Though in this particular example you don't strictly require a custom copy constructor or a custom copy assignment operator, they may be needed in other situations. Refer to the rule of three.

  •  Tags:  
  • c
  • Related