Hi!

The code below is not idiomatic (std::remove_if would have been better, or at least using ), but, to my understanding, correct (and does not trigger warnings with GCC 12 or Clang 18): the std::vector::erase does not invalidate iterators pointing to the elements before the erased one, only iterators and references to elements at the point of erasure and after. We decrement it before the erasure happens, so it points to the "stable" part of the vector:

#include <vector>

void remove_zeros(std::vector<int> &v)
{
    for (auto it = v.begin(); it != v.end(); it++)
        if (*it == 0)
            v.erase(it--);
}

With git commit e427162e887755a04d1d1af22d7f8f6868b8c602:

$ cppcheck --std=c++17 test.cpp 
Checking test.cpp ...
test.cpp:5:31: error: Using iterator to local container 'v' that may be invalid. [invalidContainer]
    for (auto it = v.begin(); it != v.end(); it++)
                              ^
test.cpp:3:38: note: Passed to reference.
void remove_zeros(std::vector<int> &v)
                                     ^
test.cpp:5:27: note: Iterator to container is created here.
    for (auto it = v.begin(); it != v.end(); it++)
                          ^
test.cpp:6:17: note: Assuming condition is true.
        if (*it == 0)
                ^
test.cpp:6:17: note: Assuming condition is true.
        if (*it == 0)
                ^
test.cpp:5:34: note: Assuming condition is true.
    for (auto it = v.begin(); it != v.end(); it++)
                                 ^
test.cpp:7:15: note: After calling 'erase', iterators or references to the container's data may be invalid .
            v.erase(it--);
              ^
test.cpp:3:37: note: Variable created here.
void remove_zeros(std::vector<int> &v)
                                    ^
test.cpp:5:31: note: Using iterator to local container 'v' that may be invalid.
    for (auto it = v.begin(); it != v.end(); it++)
                              ^