0

How do i can free mamory in next example. vt.pop_back() deletes element in vt, but it doesn't free memory. delete vt[i] doesn't work, and it give me segmentation fault.

#include <vector>
#include <unistd.h>

using namespace std;

const int SIZE = 1000000;

class Test
{
public:
    Test();
    ~Test();    
private:
    int *arr;    
};


int main()
{
    vector<Test *> vt;
    for(int i = 0; i < 100; i++)
        vt.push_back(new Test());
    sleep(10);
    return 0;    
}


Test::Test()
{
    arr = new int[SIZE];
}


Test::~Test()
{
    delete[] arr;
}
k_zaur_k
  • 400
  • 1
  • 6
  • 16
  • Why `delete v[i]` doesn't work? There is no `delete v[i]` in this code. – Rafał Rawicki Apr 09 '12 at 10:16
  • because constructor may consist arguments – k_zaur_k Apr 09 '12 at 10:16
  • @k_zaur_k: You can use `vector` for `arr` too. – Naveen Apr 09 '12 at 10:18
  • 2
    I would strongly recommend not doing this. If you make a vector of pointers, attempts to copy the vector will not do what you expect, pops will need delete's, and it will generally lead to pain and suffering as you have to wrap every vector operation to make it do the right thing with the pointers and memory. Boost's [ptr_vector](http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/ptr_vector.html) would be an example of a much better way to do this. – David Schwartz Apr 09 '12 at 10:19
  • possible duplicate of [Does vector::erase() destroy the removed object?](http://stackoverflow.com/questions/6353149/does-vectorerase-destroy-the-removed-object) – Alok Save Apr 09 '12 at 10:19

4 Answers4

6

You are not storing "Test" objects, you are storing pointers to these objects. So delete does nothing but delete the pointers.

If you want your objects to be stored in the vector you should make the type

vector<Test>

This way the delete calls actually run the destructor of the objects.

The resulting code becomes:

int main() 
{
    vector<Test> vt; 
    for(int i = 0; i < 100; i++) 
        vt.push_back(Test());
    sleep(10);
    return 0;
}

As commented this also requires a new copy constructor:

Test::Test(const Test& t)
{
    arr = new int[SIZE];
    for(int i = 0; i != SIZE; i++)
        arr[i] = t.arr[i];
}
Martin Kristiansen
  • 9,875
  • 10
  • 51
  • 83
  • 1
    Don't worry, I'm not stealing anything ;) Happens all the time: I take too long to post an answer and end up deleting it because there's a similar one already :) Have a +1. – R. Martinho Fernandes Apr 09 '12 at 10:24
  • @R.MartinHoFernandes: I know, especially on questions like this one. lots of people answer in minuts -- and most of them basically have the same answer :) – Martin Kristiansen Apr 09 '12 at 10:26
  • 1
    but vector vt; for(int i = 0; i < 100; i++) vt.push_back(Test()); doesn't work – k_zaur_k Apr 09 '12 at 10:27
  • 1
    @R.Martinho - Your answer was more complete and I was going to upvote it because of that. And then it just disappeared... – Bo Persson Apr 09 '12 at 10:27
  • 1
    if i write vector vt; for(int i = 0; i < 100; i++) vt.push_back(Test()); g++ main.cpp -o main && ./main gives me segmentation fault; – k_zaur_k Apr 09 '12 at 10:33
  • 1
    @k_zaur_k: That's because your `Test` class breaks the [Rule of Three](http://stackoverflow.com/questions/4172722) and can't be safely copied. `push_back` copies a temporary object into the vector, and destroys the original, deleting the array it allocated. – Mike Seymour Apr 09 '12 at 10:38
  • @k_zaur_k: you are right. I have added a copy constructor to handle that problem – Martin Kristiansen Apr 09 '12 at 10:39
4

You can use delete vt[i] like this, it will free the memory allocated to Test objects:

for(size_t i = 0; i < vt.size(); ++i)
{
   delete vt[i];
}
vt.clear();
Naveen
  • 74,600
  • 47
  • 176
  • 233
1

You are storing pointers and not objects, therefor the "pointer object" is going to be destroyed if you destroy your vector but not the object the pointer points to

Sebastian Hoffmann
  • 11,127
  • 7
  • 49
  • 77
0

If you want to delete specific elements, you could try using the function erase of std::vector.

eSedano
  • 312
  • 2
  • 13