Luca Guarro
Luca Guarro

Reputation: 1168

Invalid pointer operation error when calling vector.erase() function

I am using vector::erase() function to delete the the first element in the vector until it is empty but my compiler is giving me an "Invalid Pointer Operation" error.

I have a vector of class-defined objects, foo, called bar. I am deleting elements one by one like so:

for(int i = 0; i < bar.size(); i++){ 
        if(!bar.empty()){
            bar.erase(bar.begin()); 
        }
}

When I run my program, it only completes one iteration (no matter the size) and breaks on the second. Specifically, it breaks on the STL function _Destroy

template<class _TyDtor> inline
    void _Destroy(_TyDtor _FARQ *_Ptr)
    {   // destroy object at _Ptr
    _DESTRUCTOR(_TyDtor, _Ptr);
    }

*note I know there is a clear function that would do this more neatly but this is just a simplified example of something else that I am trying to do

Upvotes: 0

Views: 890

Answers (2)

Mudi
Mudi

Reputation: 131

The problem is the condition part of the loop bar.size() which keeps changing in each iteration i.e., decreasing in this example by 1.

It is difficult to say what exactly you are trying to achieve within the loop but if you want to execute the loop bar-size () times then use the follow logic:

const size_t vecSize = bar.size ()
for(int i = 0; i < vecSize ; i++) 
{ ..... }

Otherwise if you want to execute the loop till bar-size () is empty, then use the while loop as follows:

while (bar.size > 0)
{ ..... }

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 477580

As always when modifying a range while traversing the range, you cannot unconditionally increment the loop counter.

Consider the simple example of a two-element set. When i is 0, you remove the first element and increment i. Now i is 1 and bar.size() is 1, and the loop exits, failing to delete the second element.

The standard solution is to make the increment conditional on not modifying the container:

for (int i = 0; i < bar.size(); /* no increment here */) { 
    if (!bar.empty()) {
        bar.erase(bar.begin());
    } else {
        ++i;
    }
}

When you do modify the container by erasing an element, i stays constant but the range moves one element closer to it. Also incrementing i would be double-counting.

(This is an extremely common mistake, though usually it's expressed in terms of iterators, e.g. here or here or here.)

Upvotes: 2

Related Questions