0

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

Luca Guarro
  • 1,085
  • 1
  • 11
  • 25

2 Answers2

2

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

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    @aschepler: I blame the question for not matching my answer :-) – Kerrek SB Mar 22 '17 at 23:43
  • TBH, a better fix would be `while (!bar.empty()) { bar.erase(bar.begin()); }`, or even `bar.clear();`, although that still wouldn't explain the crash. The code in the OP's question, while probably wrong, isn't (directly) what is causing the crash. – cdhowie Mar 23 '17 at 00:23
  • @cdhowie: well, yes, but I'm assuming that the condition is just a stand-in and not actually representative. – Kerrek SB Mar 23 '17 at 00:25
0

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)
{ ..... }
Mudi
  • 131
  • 7