1

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.

olha
  • 2,132
  • 1
  • 18
  • 39

1 Answers1

1

Since Effective STL came out, there are shorter and more readable ways to do this. For example, you can now write

vector<int *> a{new int{1}, new int{2}};
for_each(begin(a), end(a), [](int *p){delete p;});

where [](int *p){delete p;} is an lambda or, anonymous, function saying to delete any p, in much shorter code than either of the classes in your question.

As an aside, you might also want to consider a vector of 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:

  1. 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.

  2. It is fine to pass pointers by value (in this case).

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185