3

I have a class that contains pointers, the class inherits nothing

class MyClass
{
public:
MyClass();
~MyClass();

private:
//i have pointers here
};
MyClass::~MyClass()
{
print("destroyed..");
}

Now i have to use this class as a pointer in vector like this:

vector<MyClass*> classes;

Push some classes in here but when i remove an element:

classes.remove(index);

The destructor doesn't get called,and i think that I have a memory leak.
So how do i make it call the destructor

Stormenet
  • 25,926
  • 9
  • 53
  • 65

7 Answers7

3

A vector of pointers does nothing to delete the pointers when they get removed or cleared from it. The vector cannot know if the pointers are dynamically allocated or not. It is not it's job to call delete.

It is up to you to call delete on the pointers, if and when it is necessary. There are not enough details in your question to determine whether it is necessary at all (you haven't shown how the objects pointed to are allocated). But since you claim there is a memory leak, this could indicate that they are dynamically allocated. The immediate solution is to call delete:

delete *it;
classes.erase(it); // vector has no remove member function

A safer solution is to store unique ownership smart pointers, such as std::unique_ptr<MyClass>. The standard library also provides smart pointers for shared and weak ownership. See Smart Pointers.

All the above is assuming that you do actually need to store a pointer. In general, it is safer and clearer to store values:

std::vector<MyClass> classes; // but don't call it "classes". A vector stores objects.
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 1
    You could use smart pointers to automate the deletion, if you own the pointees or are willing to deal with the overhead of a shared pointer (and don't have circular references). The first priority, though, should be to know for sure who owns the objects. (That'd help you determine what type of smart pointer to use.) – cHao Sep 09 '13 at 06:32
  • @cHao I added something about smart pointers. – juanchopanza Sep 09 '13 at 06:52
2

That's one of the reasons why you should avoid using std::vector<MyClass*> at first place. There's an ugly memory management connected with it and it won't stay as easy as classes.remove(index);

Basically, for every new a delete must be called and for every new[] a delete[] must be called, no matter whether you use this pointer as a local variable or you put it into the vector:

vector<MyClass*> vec;
vec.push_back(new MyClass());     // <-- object has been created
...
delete classes[index];            // <-- object shall be destructed
// the delete call will automatically invoke the destructor if needed
...
// now you can remove the dangling pointer from the vector

Just note that once the object has been destructed, any (old) reference to this object is invalid and trying to access this object using such reference (dangling pointer) will yield undefined behavior.

LihO
  • 41,190
  • 11
  • 99
  • 167
  • i have to use this std::vector,because the program is in Qt creatot IDE and the constructor of the QWidgts is private so i can't mke my own constructor,because i can't copy the dataof a widget pointer to an other –  Sep 09 '13 at 06:47
  • and thanks that is the best answer i guess. –  Sep 09 '13 at 06:51
  • @BerrimaHadjtahar: You're welcome. And to previous comment: in case you're working with some API, constructors and destructors of classes from this API are within the scope of internal implementation of this API. – LihO Sep 09 '13 at 06:55
1

Firstly, std::vector has no remove, you probably mean erase.

Secondly, you need to manually call delete on whatever you're removing:

vector<MyClass*> classes;
auto iter = <iterator to index to remove>;
delete *iter;;
classes.erase(iter);

Or, to avoid all this pain, use a std::unique_ptr<MyClass>.

Yuushi
  • 25,132
  • 7
  • 63
  • 81
0

You have to manually delete your pointers before your application exit or after your class object is removed from vector.

// Delete all
vector<MyClass*>::iterator it = classes.begin();
while (it != classes.end()) {
    delete *it;
    it = classes.erase(it);
}

Tip: Never add stack constructed pointers like following:

MyClass m;
classes.push_back(&m);

Edit: As suggested by other member the better solution is:

MyClass m(/* ... */);
vector<MyClass> classes;
classes.push_back(m);

However please note, you have to properly implement the copy constructor especially if your class has pointer data members that were created with new.

bkausbk
  • 2,740
  • 1
  • 36
  • 52
  • hi,thanks,,,vector classes; classes.push_back(m);,,, is not an option,the elements must be pointers, –  Sep 09 '13 at 06:59
0

Make a temp pointer to hole MyClass* pointer before you remove it from your vector.

vector<MyClass*> classes;

//push some classes in here but
//when i remove an element
MyClass* temp = classes[index];
classes.remove(index);

// call delete temp;  if you want to call the destructor thus avoid memory leak.
delete temp;

To avoid memory leak, remember never to loose control of heap object, always keep a a pointer or reference to it before object release.

lulyon
  • 6,707
  • 7
  • 32
  • 49
0

It is unclear who is responsible for managing the lifetime of the objects pointed by the pointers inside classes. Have you pushed newed pointers into it, or have you pushed the addresses of automatic storage objects?

If you have done the former, then you must manually delete the pointer before removing it. Else, if you have done the latter, then you could just leave it as is, just leaving the pointed-to objects destroy themselves as they leave their respective scopes. If you have mixed newed and non-newed pointers, whose possibility isn't that remote as you would think, then you're definitely damned, undefined behavior making demons fly out of your nose.

These kinds of situations involving pointers are very ambiguous, and it is generally recommended not to use pointers at all, and make the std::vector store plain objects, which makes your object lifetime management much simpler and the making the declaration just speak for itself.

vector<MyClass> classes;  // Do this instead
Mark Garcia
  • 17,424
  • 4
  • 58
  • 94
  • i'm only pushing with (new MyClass) so, i guess no demons flying ,the thing is i have to make the pointers it's a must –  Sep 09 '13 at 06:43
0

It seems that you want your vector to be manager of your items.
Take a look at boost::ptr_vector class
its basically a wrapper around std::vector class.
You declare that this vector is the "holder" of these pointers, and if you remove them from this containers you want them to be deleted.

#include <boost/ptr_container/ptr_vector.hpp>
...
boost::ptr_vector<MyClass> myClassContainer;  
myClassContainer.push_back(new MyClass());
myClassContainer.clear(); // will call delete on every stored object!
Aleksander Fular
  • 803
  • 9
  • 18