SolidSun
SolidSun

Reputation: 2189

Constructor/Destructor call order on stack

I have the following simple code:

class A
{
    int a;
public:
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; }
    ~A()            { cout << "Destructor  a=" << a << endl; }
    void print()    { cout << "Print       a=" << a << endl; }
};

void f()
{
    A a(1);
    a.print();
    a = A(2);
    a.print();
}

int main()
{
    f();
    return 0;
}

The output is:

Constructor a=1
Print       a=1
Constructor a=2
Destructor  a=2
Print       a=2
Destructor  a=2

I find that there are two destructor calls with a=2 and none with a=1 while there is one constructor call for each case. So how are contructors and destructros called in this case?

Upvotes: 6

Views: 725

Answers (5)

Arun
Arun

Reputation: 2092

void f()
{
    A a(1); // Constructor a=1 (a.a(1) is called)
    a.print(); // Print a=1
    a = A(2); // Constructor a=2 (Temporary unnamed object A(2) is constructed)
              // compiler generated a.operator=(const A&); is called and then
              // Destructor  a=2 (Temporary unnamed object is destroyed.
    a.print(); // Print a=2
              // Destructor  a=2 (a.~a() is called)
}

Upvotes: 2

Vyktor
Vyktor

Reputation: 20997

This is because you're not destroying A(1) you're assigning A(2) to it, let's extend your example by adding assign operator:

class A
{
    int a;
public:
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; }
    ~A()            { cout << "Destructor  a=" << a << endl; }
    void print()    { cout << "Print       a=" << a << endl; }
    A &operator=(const A &other) {
        cout << "Assign operator old=" << a << " a=" << other.a << endl; 
        a = other.a;
    }
};

Which will result to:

[vyktor@grepfruit tmp]$ ./a.out 
Constructor a=1
Print       a=1
Constructor a=2
Assign operator old=1 a=2 <- This line explains why destructor is not called
Destructor  a=2
Print       a=2
Destructor  a=2

If you have one of these implemented:

  • Destructor - Destruct all the object's members
  • Copy constructor - Construct all the object's members from the equivalent members in the copy constructor's parameter
  • Copy assignment operator - Assign all the object's members from the equivalent members in the assignment operator's parameter

you should implement all of them. This is called rule of three.

Upvotes: 2

Mohit Shah
Mohit Shah

Reputation: 862

First the constructor for a=1 is called

Second the print is called

Third the new object which you created A(2) has its constructor called.

Fourth this object is assigned to object a so data member of object a=2

Fifth the destructor for object A(2) is called

Sixth the destructor for object a is called

Upvotes: 1

alexrider
alexrider

Reputation: 4463

a = A(2);

Will use default operator= to assign new value to a, setting it's a::a member value to 2.

void f()
{
    A a(1);//a created with int constructor a.a == 1
    a.print();// print with a.a == 1
    a = A(2);//Another A created with int constructor setting a.a == 2 and immediately assigning that object to a
    //object created with A(2) deleted printing 2 it was created with
    a.print();//a.a==2 after assign
}//a deleted printing 2 it was assigned with

You probably should read about Rule of three to get better understanding what's going on.

Upvotes: 7

awesoon
awesoon

Reputation: 33671

void f()
{
    A a(1);
      //  Constructor a=1
    a.print();
      //  Print       a=1
    a = A(2);
      // Constructor a=2
      // also operator=
      // Destructor  a=2
    a.print();
      // Print       a=2
      // Destructor  a=2
}

Upvotes: 4

Related Questions