tags:

views:

430

answers:

4

Hello,

I am using borland 2006 c++, and have following code. I am using vectors, and have trouble understanding why the destructor is not being called.

basically i have a class A

class A
{
private:
    TObjectList* list;
    int myid;
public:
 __fastcall A(int);
 __fastcall ~A();
};

__fastcall A::A(int num)
{
    myid = num;
    list = new TObjectList();

}

__fastcall A::~A()
{
    delete list;
}

int main(int argc, char* argv[])
{
    myfunc();
    return 0;
}

void myfunc()
{
    vector<A*> vec;
    vec.push_back(new A(1));
    vec.push_back(new A(2));
}

according to what i read, when variable vec goes out of scope in myfunc(), it should destruct its contained elements, so the destructor for A should be called. I have a breakpoint at ~A(), but never gets called, i have tried resize(), erase methods also

TIA

+15  A: 

vec does destruct its elements when it goes out of scope. The problem here is that vec's elements are the pointers to A objects, not A objects themselves. If you instead did

vector<A> vec;
vec.push_back(A(1));
vec.push_back(A(2));

...then things would work as you expect.

ETA: note, though, that if you do this you have to define a copy constructor for A. That should involve doing a deep copy of the TObjectList member. Otherwise, when you copy an A object you'll wind up with two objects both pointing to the same TObjectList, and your program will crash when the second object is destroyed.

David Seiler
As a side note. Do not try and use auto_ptr in order to do the destruction while using pointers within the container. Auto_ptrs are not able to be used inside STL containers due to how they are copied.
RC
Right, but boost::shared_ptr<> AKA std::tr1::shared_ptr<> do work nicely in container classes.
David Thornley
thanks for the explanation, another quick issue is when i add one element to vector, the destructor is called twice, and once again when vec goes out of scope, i expect it to call once when element is copied and added..
No, it's supposed to be called twice. What happens is that you are creating a temporary, anonymous A object and passing it to vector's push_back method. Vector then makes a copy of that temporary A object to store internally. Immediate after returning from push_back, the temporary A object falls out of scope and is destructed. then, when the vector itself falls out of scope and destructs, it destructs the copied A object that it holds. This is why you need a copy constructor for A that does a proper, deep copy.
Tyler McHenry
+3  A: 

The destructor for A isn't called because you don't have a vector of A. You have a vector of pointers to A, and the destructors for the pointers are called. Pointers don't have a destructor, so nothing happens.

One way to delete everything would be to manually do something like

while (!vec.empty())
{
    delete vec.back();
    vec.pop_back();
}
rlbond
+1  A: 

Grab the Boost libraries, and wherever you have a raw pointer in the above you use boost::shared_ptr<> instead. (Well, not in the signature of main().)

David Thornley
+2  A: 

Lots of good answers already, but I'll add one more:

Use boost::ptr_vector from the Boost Pointer Container Library, instead of std::vector. It will delete the objects when the vector goes out of scope, thus calling the destructors.

Mark Ransom