5

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?

SolidSun
  • 2,149
  • 2
  • 23
  • 28

5 Answers5

7
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.

Community
  • 1
  • 1
alexrider
  • 4,449
  • 1
  • 17
  • 27
4
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
}
awesoon
  • 32,469
  • 11
  • 74
  • 99
2

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.

Vyktor
  • 20,559
  • 6
  • 64
  • 96
2
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)
}
Arun
  • 2,087
  • 2
  • 20
  • 33
1

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

Mohit Shah
  • 843
  • 1
  • 6
  • 20