Skip to main content
GameDev.net gamedev.net
🔒 Locked

c++ - vector in destructor

Started by pundit Jun 2, 2008 at 8:02 AM 9 replies 11.6k views
Original Post
pundit
pundit
Hello everyone, i have a question: I'm currently making a list class which is containing the following vector: private: static std::vector* m_COPtrVectorPtr ; //i have a method/member function that adds a new ControlObject as follows: void COList::Add() { m_COPtrVectorPtr->push_back(new ControlObject()); } Now my question is about the destructor of the class, which i have here: COList::~COList() { //anything before this? if (m_COPtrVectorPtr!=0) delete m_COPtrVectorPtr; } Since this is a vector which contains pointers to other objects i was wondering that when i call this destructor/delete an object of the class i'm writing, does the vector handle its own destruction without memory leaks? Does it delete the objects and frees up the memory to which its pointers are leading? If not, how do i do this correctly? Thanks in advance and friendly greetings, pundit ^^
Mathmo
Mathmo
No, I think that the vector will not delete those pointers for you, as that could cause problems.

Test it - put a line in the destructor of one of the objects so that it prints to a file when deleted, and run it - then you can find out if they are being deleted!

I would use an iterator to iterate through the vector deleting the pointers - google stl iterators.

or maybe just
for ( size_t n = 0; n < myvector->size(); ++n){    delete (*myvector)[n];}// if you know that they will all have been created// elsefor ( size_t n = 0; n < myvector->size(); ++n){    if ( (*myvector)[n] != 0 )         delete (*myvector)[n];}


Hope that helps
Mathmo
Bonedry
Bonedry
Since you are allocating the ControlObjects dynamically, you will have to deallocate them manually as well. An easy way to do this it to loop over your vector, deleting each element, before deleting the vector itself.

Easier, though, and often safer, would be to use some kind of smart pointer, like boost::shared_ptr, instead of plain pointers. You can have both your private vector and its elements as smart pointers. Then you will not have to do any deallocation yourself, since the destructors for the smart pointers will automatically take care of that.
pundit
pundit
Ok, thanks for your help! Much appreciated!
Antheus
Antheus
That static in there is a disaster. Why is the vector static?

If you need a global, declare the class as global.

// helper function for all deletionstemplate < class T >void deleter(T * ptr) {  delete ptr;}class COList : private boost::noncopyable { // prevent copyingpublic:  ~COList()  {    std::for_each(control_objects.begin(), control_objects.end(), deleter) ;  }private:  std::vector< ControlObject* > control_objects; // no pointer};
pundit
pundit
The vector is static because i'll only need it once. It's not necessary that i put it there as i will only make one COList anyway. But i thought better safe than sorry?
Why is it a disaster?
Spoonbender
Spoonbender
Quote:
Original post by pundit
The vector is static because i'll only need it once. It's not necessary that i put it there as i will only make one COList anyway. But i thought better safe than sorry?
Why is it a disaster?


The obvious problem is that once sooner or later you're going to create two anyway. You risk introducing some annoying bugs.

And what exactly is the benefit?
Performance? Not at all. If anything, you'll get an extra cache miss on accessing the static version, because it won't be conveniently located on the stack along with all the other local variables. And at best, it won't make a difference.

How is this "better safe than sorry"?
Writing error-prone code with no benefits is not "better safe than sorry".
pundit
pundit
Okay, good to know that. Thanks!

Antheus
Antheus
Quote:
Original post by pundit
The vector is static because i'll only need it once. It's not necessary that i put it there as i will only make one COList anyway. But i thought better safe than sorry?
Why is it a disaster?


Since you aren't too sure about allocations and destructors, it's safe to say you've missed out on other C++ features as well.

Are you sure there will only be one? What happens if you by mistake pass the instance by value? Do you prevent the copying? Under which situations will C++ compiler automatically copy-construct or assign a new instance?

This remains a problem even if the array isn't static. This is why I added noncopyable.

Implementing rule-of-three with raw pointers this way is tricky at best. Once you have two instances, who cleans up? Each destructor will clean its own array, but delete shared objects.

If you do use static storage, then make accessors static as well. You're not gaining anything by mixing both. Then again, you also gain *nothing* by declaring everything static.

If there will only ever be one instance, then:
static COList myList;
does exactly that, without all the pitfalls of mixing concepts.
pundit
pundit
Once again, that was very interesting ^^ It's true, it doesn't have to be static as there isn't much use there. You've all been a great help!
d000hg
d000hg
By the way, you can call delete on a null (0) pointer, you don't need to check the pointers.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.