You don't necessarily need iterators. As you say, you can do it by IDs. Or you can do it by pointer, because if you were storing pointers in the container, they don't change even when the container grows and shrinks. The pointer way is potentially dangerous if you aren't sure whether the object you point to is still in existence when you try to delete it. But so are iterators, if you don't know whether they got invalidated or not. With an std::list, they almost never get invalidated, unless you erase the very element that an iterator currently points to - which is probably exactly what your current design does.
If you do need to remove an object from a std::list while iterating over it, the answer is actually quite simple - make sure you've incremented the relevant iterator before you erase it. (Usually this means copying the iterator, incrementing it, then erasing whatever the copy points to.) This is obviously not practical when each object is holding its own iterators as you'd have to go in to each object and see if they have a copy of that iterator and clear it.
You can always store 'full' objects instead of std::list instead of pointers to them. In that case, you have to be careful if you ever move to using std::vector, because the semantics are different. I mentioned storing pointers above because I'd misread and thought you were using vectors already (most people don't use std::list), but with a list storing the full object is more reasonable. This is largely independent of what you do with iterators, however.