Your problem here is your anEntry
copy constructor is broken. The default copy constructor (anEntry (const anEntry &)
) simply copies all members; with your class's explicit destructor, this results in double freeing. The same applies for the default operator=
. Per the Rule of Three, if you define any one of a destructor, copy constructor, and operator=
, you should generally implement the other two (or forbid them by making them private and unimplemented); otherwise there's a good chance the default implementation of one of them will cause problems like this.
Now, the vector
class requires a working copy constructor. This is part of the vector
contract. If your class has a missing (ie, forbidden by making it private) copy constructor, the compiler will error out, preventing these "serious side effects". If the class has a broken copy constructor, well, that's not vector
's fault.
Note that you may want to consider using RAII-style allocation in your anEntry
class. For example, make iDM2P2H
a std::vector<otherClass>
instead of std::vector<otherClass> *
. By doing so, you won't need a destructor at all, and if the default copy semantics are acceptable to you, you might be able to do with the default copy constructor in this case.
That said, vector
's copying may indeed entail significant overhead at times. There are a number of things you can do to work around this; however I would recommend against a raw std::vector<anEntry *>
- the reason being that this won't clean up the pointed-to elements automatically.
Instead, use a std::vector<std::unique_ptr<anEntry>>
(if you have a C++0x compiler) or boost::ptr_vector<anEntry>
. This will give you the automatic destruction benefits of vector
but will not copy any elements (as the vector is a vector of pointers to objects). Note that in the unique_ptr
case you will need to use std::move
to add elements to the vector.
Alternately, if your compiler supports C++0x move-aware containers, you could write a move constructor:
struct anEntry {
Thing *thing;
std::vector<sqdDMPair> iDM2P2H;
anEntry(Thing *thing_, std::vector<sqdDMPair> *vec = NULL)
: thing(thing_), iDM2P2H(vec ? *vec : std::vector<sqdDMPair>())
{ }
// Default copy constructor and destructor OK
// Move constructor
anEntry(anEntry &&src)
: thing(src.thing), iDM2P2H(std::move(src.iDM2P2H)) { }
anEntry &operator=(anEntry &&other) {
if (this != &other) {
thing = other.thing;
iDM2P2H = std::move(other.iDM2P2H);
}
}
};
Using std::move
allows the contents of iDM2P2H
to be moved to the new position in the outer vector without copying recursively. However, C++0x support is still in its infancy, and your compiler and STL may or may not support it yet (if std::vector<std::unique_ptr<int>>
compiles, you're probably ok).