Why the constructor is called twice

I do not understand how constructors work ?

Here I declared an obj2 object. It calls the abc() constructor, which works great.

But when I appoint

 obj2 = 100 

Why does the compiler allow initialization of an entire class to a class object? If it permits at all, how does it destroy the object, and then how does it invoke another parameterized constructor.

Now I have another question, why is the destructor called only once since there are two objects?

Another doubt is that the compiler is not doing anything with the default constructor , why is the default constructor required ?

 class abc{ public: int a, b; abc() {a = 0; b = 0;} abc(int x) {a = x;} ~abc() {std::cout << "Destructor Called\n";} }; int main() { abc obj1; cout << "OBJ1 " << obj1.a << "..." << obj1.b << "\n"; abc obj2; cout << "OBJ2 " << obj2.a << "..." << obj2.b << "\n"; obj2 = 100; cout << "OBJ2 " << obj2.a << "\n"; system("pause"); return 0; } 

output:

 OBJ1 0...0 OBJ2 0...0 Destructor Called OBJ2 100 
+6
source share
5 answers

Let's play the show and tell, so let's use all the special participants:

 #include <iostream> class abc{ public: int a, b; abc() { std::cout << "Default constructor\n"; a = 0; b = 0;} abc(int x) { std::cout << "Int constructor\n"; a = x;} abc(abc const& other): a(other.a), b(other.b) { std::cout << "Copy constructor (" << a << ", " << b << ")\n"; } abc& operator=(abc const& other) { std::cout << "Assignment operator (" << a << ", " << b << ") = (" << other.a << ", " << other.b << ")\n"; a = other.a; b = other.b; return *this; } ~abc() {std::cout << "Destructor Called\n";} }; int main() { abc obj1; std::cout << "OBJ1 " << obj1.a << "..." << obj1.b << "\n"; abc obj2; std::cout << "OBJ2 " << obj2.a << "..." << obj2.b << "\n"; obj2 = 100; std::cout << "OBJ2 " << obj2.a << "\n"; return 0; } 

And we get this conclusion :

 Default constructor OBJ1 0...0 Default constructor OBJ2 0...0 Int constructor Assignment operator (0, 0) = (100, 0) Destructor Called OBJ2 100 Destructor Called Destructor Called 

So, let's reconcile them with string sources:

 int main() { abc obj1; // Default constructor std::cout << "OBJ1 " << obj1.a << "..." << obj1.b << "\n"; // OBJ1 0...0 abc obj2; // Default constructor std::cout << "OBJ2 " << obj2.a << "..." << obj2.b << "\n"; // OBJ2 0...0 obj2 = 100; // Int constructor // Assignment operator (0, 0) = (100, 0) // Destructor Called std::cout << "OBJ2 " << obj2.a << "\n"; // OBJ2 100 return 0; // Destructor Called // Destructor Called } 

You basically had everything, let's look at surprises.

First surprise: even if obj2 changes the value later abc obj2; it will still call the default constructor at the declaration point.

Second surprise: obj2 = 100 actually means obj2.operator=(abc(100)); , i.e:

  • Create a temporary (unnamed) abc from abc(100)
  • Assign it to obj2
  • Destroy the temporary before moving on to the next statement

Third surprise: destructors are called at the end of the area, right before the closing bracket } (and yes, after return ). Since you use system("pause") , I assume that you are on Windows => although the luck they cause after the pause is complete, and thus your Windows console disappears in the blink of an eye the moment they appear. You can run the program from a more permanent console or use an additional area:

 int main () { { // your code here } system("pause"); return 0; } 
+3
source

But when I assign obj2 = 100, how does the compiler allow initialization of the whole class to the class object?

This is because when you do the following:

 obj2 = 100; 

this one will first call abc(int x) to generate the class object, then call the default assignment operator (since it is not defined by the user) to assign the value 100 to existing obj2 . After the appointment, the temporary object is destroyed.

If you do not want this effect, mark the destructor as explict to avoid implicit calls.

 explicit abc(int x) { //do something } 
+6
source
  obj2 = 100; 

You have defined a constructor that accepts an int . This allows an implicit conversion from int to abc . This requires the creation of a new object. It does not just magically set a field in an existing object, invoking the constructor; designers create new objects.

EDIT: correct sequence of events from @Steve Jessop

A new instance is created, then copied to the original, then temporarily (and not the original) is destroyed. Assigning a copy truly magically sets both fields in an existing object.

+5
source

This is because there is a constructor that can accept an argument of type int . This temporary created object is copied to obj2 by calling the default copy destination.

To avoid such transformations, create a constructor as explicit.

+1
source

You are the destructor called 3 times, you cannot see it due to a pause.

+1
source

Source: https://habr.com/ru/post/954803/


All Articles