In his "Effective STL" Meyers show how to clean vector of pointers correctly (std::vector::clear deletes only his pointers, and not the memory they occupy).
So he advices before the call to clear use for_each with unary_function which calls object destructor:
template<typename T> struct DeleteMyObject2: public std::unary_function<const T*, void>
{
void operator()(const T* ptr);
};
template<> struct DeleteMyObject2<algotest::ImageSelection>
{
void operator()(const algotest::ImageSelection* ptr)
{
delete ptr;
ptr=0; // this was added by me
}
};
void std_clearing_pointers()
{
std::vector<ImageSelection*> vec;
vec.reserve(5);
for(int i=0; i<5; ++i)
vec.insert(vec.begin(), new ImageSelection());
std::for_each(vec.begin(), vec.end(), DeleteMyObject2<ImageSelection>());
// HERE elements of vec are not NULL !!!
vec.clear();
}
In the book DeleteMyObject2 was called without parentheses, it doesn't compile (question1: why? was Standard changed?):
std::for_each(vec.begin(), vec.end(), DeleteMyObject2<ImageSelection>);
Anyway, it compiles if call operator() for DeleteMyObject2, but before vec.clear() objects in vector are not NULL's. I suppose that as STL containers copy their elements all the time, ImageSelection pointer is passed by value, so everything is okay (question2: am I correct?).
I tried passing pointer by ref, now objects are NULLs after for_each, and I feel safer.
template<> struct DeleteMyObject1<algotest::ImageSelection>
{
void operator()(algotest::ImageSelection*& ptr)
{
delete ptr;
ptr=0;
}
};
question3: is DeleteMyObject2 more preferable than DeleteMyObject1 because it hasn't unnecessary assignments?
Thanks in advance.
Since Effective STL came out, there are shorter and more readable ways to do this. For example, you can now write
where
[](int *p){delete p;}is an lambda or, anonymous, function saying todeleteanyp, in much shorter code than either of the classes in your question.As an aside, you might also want to consider a
vectorof smart pointers (e.g.,vector<shared_ptr<int>>for a vector of pointers to integers). Explicit code to deallocate resources, is error prone.As for your questions:
The class should appear with parentheses, with which you indicate you want a (default-constructed) object of this class. The function expects an object, not a class.
It is fine to pass pointers by value (in this case).