Problem with C ++ destructor with std :: vector class objects

I am confused about how to use destructors when I have std :: vector of my class.

So, if I create a simple class as follows:

class Test { private: int *big; public: Test () { big = new int[10000]; } ~Test () { delete [] big; } }; 

Then in my main function I do the following:

 Test tObj = Test(); vector<Test> tVec; tVec.push_back(tObj); 

I get a crash in the test destructor when I go out of scope. Why is this and how can I free my memory safely?

+7
c ++ memory vector destructor
source share
4 answers

Your problem is here:

 Test tObj = Test(); 

Test() creates a temporary Test object, which is then copied to tObj . At this point, both tObj and the temporary object have big to point to the array. Then the temporary object is destroyed, which calls the destructor and destroys the array. Therefore, when tObj destroyed, it tries to destroy the already destroyed array again.

In addition, when tVec destroyed, it will destroy its elements, so the array already destroyed will be destroyed again.

You must define the copy constructor and assignment operator so that when you copy the Test object, the big array is copied or has some reference count, so that it is not destroyed until all the owners are destroyed.

A simple solution is to define your class as follows:

 class Test { private: std::vector<int> big; public: Test (): big(10000) {} }; 

In this case, you will not need to define any destructor, copy constructor, or assignment operator, because the std::vector<> member will take care of everything. (But note that this means that 10,000 bytes are allocated and copied whenever you copy an instance of Test .)

+15
source share

The problem is that you are not defining a copy constructor for Test . Thus, the compiler creates a default copy constructor for you, which simply copies the contents of the object - in this case, an int pointer.

Now, when you return your object to a vector, it is implicitly copied using the copy constructor. This results in two objects pointing to the same ints array! Thus, at the end, two destructors try to delete the same array - BANG.

Whenever you define a class that owns members through pointers *, in addition to the destructor, you must also define a copy constructor for it. Update: and assignment operator for the same reason (thanks @James :-)

Update2: A trivial way to get around all these limitations is to define a static array instead of a dynamically allocated one:

 class Test { private: int big[10000]; // no need for constructors, destructor or assignment operator }; 

However, it is best to use std::vector<int> instead of an array.

* , i.e. contains pointers to members with property semantics (thanks to @Steve Jessop for clarification)

+21
source share

Without a copy constructor, the vector will create a flat copy of your object. This results in two objects of type Test referencing the same big array. The first instance deletes the array when it is destroyed, and then the second instance tries to dereference the remote pointer, which is undefined.

0
source share
 Test tObj = Test(); 

This is wrong and should be, because it does not create a copy:

 Test tObj; 

It also creates many copies:

  vector<Test> tVec; tVec.push_back(tObj); 

So, if you free one int array, you free all arrays. And the next removal will fail.

You will need:

  • use copy constructor for each class for a separate array

  • Why use a pointer?

 class Test { private: int big[10000]; public: }; 

This will work fine.

0
source share

All Articles