Destructor Request

I have this program below, where I pass a vector by reference to the myFunc function and inside this function I add several elements to the vector.

I do not release the creation of the object new, as I now ignore the memory leak because of this.

After myFunc() completes, the ctor and dtor variables are printed to find out how many times the constructor and destructor have been called.

Exit:

 Before Exiting 5 7 

I create 5 objects, so ctor is 5 . But why dtor 7 ? Where do two more bills come from? Did I miss something?

 #include #include using namespace std; static int ctor = 0; static int dtor = 0; class MyClass { public: MyClass(int n) { i = n; ctor++; // cout << "Myclass ctor " << ctor << endl; } ~MyClass() { dtor++; // cout << "Myclass dtor" << dtor << endl; } private: int i; }; void myFunc(vector<MyClass> &m); void myFunc(vector<MyClass> &m) { MyClass *mc; for(int i = 0; i < 5; i++) { mc = new MyClass(i); m.push_back(*mc); } } int main() { vector<MyClass> m; vector<MyClass>::iterator it; myFunc(m); cout << "Before Exiting " << ctor << " " << dtor << endl; } 
+6
source share
5 answers

Vectors copy objects, but only your int constructor increments ctor . This does not take into account the objects created for copying, and because you did not provide it, the compiler provided it to you.

Add

 MyClass(const MyClass& rhs) i(rhs.i) { ++ctor; } 

for your class to make sure it balances the score.

+8
source

Vectors start small. When you click on an element on them, they copy it using the copy constructor, so you do not see that your normal constructor is called. When the size of a vector grows beyond its limit, it will increase its limit by a multiple of its current size (for example, double it).

Vectors always store objects in contiguous memory, so if adding a new object exceeds the number of capacity () vectors (i.e. size () + 1> capacity ()), the vector allocates a new memory somewhere and copies all the elements to It. This will again use the copy constructor. Thus, your elements from the vector preliminary change will call their destructors after they are copied to the new allocated space using their copy constructor.

So, there are more destructor calls than regular constructor calls :)

+2
source

Vectors are sometimes called another constructor, a copy constructor, which is implicitly generated by the compiler for your class. That's why some ctor++ calls ctor++ missing: not all objects were constructed with the constructor you defined, some of them were built with another.

To ensure the correct behavior of a type (class) with a vector, you must implement a copy constructor for it:

 MyClass(const MyClass& rhs) { i = rhs.i; ++ctor; } // copy constructor 

... because the one generated by the compiler does nothing.

+1
source

As pointed out by others, the reason for your result is the copy constructor and the vector resizing. A vector has size and capacity. Typically, capacity is usually doubled when vector needs to resize to accommodate new elements, so resizing should not occur frequently.

Adding some trace code to print the vector capacity between each push_back gives more clarity in this behavior.

 m.capacity(): 0 m.capacity(): 1 m.capacity(): 2 m.capacity(): 4 m.capacity(): 4 m.capacity(): 8 Before Exiting 5 7 

What actually happens here is that the only time the destructor is called is to resize the vector (see why below). The first time he resized, he has no elements, so the destructor is never called. The second time, the capacity is 1, so the destructor is called once. The third time he was called twice, and the fourth time he was called four times. This number is called seven times in the same way as the counter shows.

Elements dynamically allocated in myFunc are never freed, so the destructor never works there, and the final printout ("Before exiting ...") is performed before leaving the area where vector is selected, therefore the destructor for the last "vector reincarnation "is not called only after this listing. Therefore, the MyClass destructor is called only when the vector is resized.

+1
source

Section 12.8.8 of the C ++ standard says: If the class definition does not explicitly declare a copy constructor, there is no user-declared move constructor, and there is no user-declared move assignment operator, a copy constructor is implicitly declared as defaulted (8.4.2). Such an implicit declaration is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. If the class definition does not explicitly declare a copy constructor, there is no user-declared move constructor, and there is no user-declared move assignment operator, a copy constructor is implicitly declared as defaulted (8.4.2). Such an implicit declaration is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

Basically, since your structure breaks the rule of five options , the compiler made a constructor and an assignment operator for you. This other constructor does not increment ctor, but uses the destructor that you defined. The vector then uses this alternative constructor as an improvement in speed.

If you add protected: MyClass(const MyClass& b); in the class declaration, this problem will disappear.

0
source

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


All Articles