Reputation: 2261
I have a map that relates integers to vectors (of objects). These vectors represent a set of tasks to perform. In order to reduce the amount of copying going on while using this map and vector I've set them up to make use of pointers.
std::map<int, std::vector<MyObject *> *> myMap;
During initialization of the class that holds myMap, I populate myMap by creating a new vector filled with new MyObjects.
What I'm concerned with, however, is memory management. Now I have these various objects sitting out on the heap somewhere and I am responsible for cleaning them up when I'm done with them. I also know that I will NEVER be done with them until the program is finished. But what about in 10 weeks when someone decides that a clever way to modify this app involves removing items from the map/vectors. This would cause a memory leak.
My question is how can I handle the proper deallocation of these objects so that even if they get removed via an STL function that the objects get successfully deallocated?
Your help is much appreciated, let me know if I've missed anything critical! Thanks!
Upvotes: 4
Views: 1563
Reputation: 25283
To elaborate on minimizing copying when using map<,vector<Object>>
:
Closely look at the interfaces of map
and vector
. They mostly return references to the contained items, and if you preserve the reference in passing these things around, no copying will occur.
Bad example:
std::vector<MyObject> find_objects( const std::map<int,std::vector<MyObject>> & map, int i ) {
const std::map<int,std::vector<MyObject>>::const_iterator it = map.find( i );
if ( it != map.end() )
return it->second;
else
return std::vector<MyObject>();
}
// ...
const std::vector<MyObject> objects = find_objects(/*...*/);
Better:
const std::vector<MyObject> & find_objects( const std::map<int,std::vector<MyObject>> & map, int i ) {
const std::map<int,std::vector<MyObject>>::const_iterator it = map.find( i );
if ( it != map.end() )
return it->second;
static const std::vector<MyObject> none();
return none;
}
// ...
const std::vector<MyObject> & objects = find_objects(/*...*/);
-> no copying
Upvotes: 0
Reputation: 2261
Thank you all for the good answers. I think currently I'm leaning towards a vector of values solution currently. The main reason is that std::auto_ptr doesn't work with collections due to the fact that it is uncopyable. This would be the only implementation of a smart pointer that I would be able to use without going through a burdensome vetting process or rolling my own.
The good news is your responses led me down a very good road. I learned about RAII, dangers about exception handling and how to minimize them, and put enough vigilance into my design that I can be satisfied with its "Correctness".
Attached are some links that I found helpful along the way. I hope that anyone coming to a similar problem will find these links helpful.
RAII Resource
Smart Pointers in C++
Boost Smart Pointers
More background/implementation details about Smart pointers
Upvotes: 1
Reputation: 8171
If the ownership of each pointer is not shared among different entries in the vectors/maps and so you only mean reducing the copying done at insertion time, then you should also consider boost's Pointer Container library.
Upvotes: 0
Reputation: 30115
Use a smart pointer boost:shared_ptr rather than raw pointers, that way when the object is destroyed it will clear up the heap allocated memory as well.
boost::shared_ptr http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm
Also is there really a reason to have pointers to the vectors? They take up almost no space, and objects within an std::map are not moved anyway (unlike the objects in a vector which are moved/copied each time the vector reallocates, eg to get more space).
EDIT: Also shared_ptr is a component of tr1, and I'm pretty sure is in the next standard, so your compiler may already have it. There are also lots of other smart pointers around that are STL safe to give you an idea of how to write your own, a quick search on Google should find them.
EDIT2: Just checked and the Visual Studio 2008 implementation of TR1 includes the shared_ptr which is included in the Visual C++ 2008 Feature Pack. I expect many other vendors have implementations available for at least parts of TR1, so if your not using VS search your vendors site for TR1 support.
Upvotes: 8
Reputation: 34711
Using a shared pointer (as suggested by others) is the best solution.
If you really know you will never be done with them, then they don't technically need deallocating. If this really is desired behaviour, just document it so that someone doesn't come along in 10 weeks and mistake this for a genuine leak.
Upvotes: 1
Reputation:
I agree the use of smart pointers is a good way to go, but there are at least two alternatives:
a) Copying may not be as expensive as you think it is. Try implementing a map of values
std::map<int, std::vector<MyObject>> myMap;
b) Replace the vector with a class of your own that wraps the vector. In that classes destructor, handle the deallocation. You could also provide methods for adding and removing MyObjects.
Upvotes: 5