c++boostptr-vector

Does ptr_vector iterator not require increments?


#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
using namespace std;

class Derived
{
public:
        int i;
        Derived() {cout<<"Constructed Derived"<<endl;}
        Derived(int ii):i(ii) {cout<<"Constructed Derived"<<i<<endl;}
        ~Derived() {cout<<"* Destructed Derived"<<i<<endl;}
};

int main()
{
   boost::ptr_vector<Derived> pv;
   for(int i=0;i<10;++i) pv.push_back(new Derived(i));

   boost::ptr_vector<Derived>::iterator it;
   for (it=pv.begin(); it<pv.end();/*no iterator increment*/ )
        pv.erase(it);
   cout<<"Done erasing..."<<endl;
}

Notice that the second for loop does not increment the iterator, yet it iterates and erases all elements. My questions are:

  1. Is my technique of iteration and using the iterator correct?
  2. If iterator increment is not required in the for loop, then where does the increment happen?
  3. Is it better to use an iterator or will an ordinary integer suffice (ie: is there any value-add with using iterators)? (coz I can also erase the 5th element like pv.erase(pv.begin()+5);)
  4. Is there any way to assign a new object to a specific position (let's say the 5th position) of ptr_vector, directly? I'm looking for something like pv[5]=new Derived(5);. Any way of doing that?

Solution

  • Is my technique of iteration and using the iterator correct?

    No, erasing from a container generally invalidates the iterator to the erased item. If it works, this is just a side-effect of the implementation details.

    The correct way would be to use the return value of the erase method:

     it = pv.erase(it);
    

    However, for emptying the container, you can use the clear member function.

    If iterator increment is not required in the for loop, then where does the increment happen?

    It doesn't happen, because you'll always be erasing the first item in the container (by chance, might not work out with other containers).

    Is it better to use an iterator or will an ordinary integer suffice (ie: is there any value-add with using iterators)? (coz I can also erase the 5th element like pv.erase(pv.begin()+5);)

    In a random-access container you can do that, otherwise not (such as a list).

    Is there any way to assign a new object to a specific position (let's say the 5th position) of ptr_vector, directly? I'm looking for something like pv[5]=new Derived(5);. Any way of doing that?

    According to the boost reference:

    pv.replace(5, new Derived(5));
    

    This returns the existing pointer in a smart pointer, so it will be automatically deallocated. (It's curious that this takes an index, not an iterator...).

    Or:

    pv[5] = Derived(5);
    

    but this will just modify the stored object, not change the pointer.