Can you change a std::list while iterating through it?
In the following functions, it it entirely possible for the IObserver's Process()
function to try to remove itself from the notify list, using the this
pointer's DeleteObserver()
.
This causes hell with the iterators (not surprisingly!), is there a way round this? Or should I be taking a closer look at my design?
void cButtonManager::DeleteObserver(IObserver *observer)
{
list<IObserver*>::iterator iter;
for (iter = m_ObserverList.begin(); iter != m_ObserverList.end(); ++iter)
{
if (*iter == observer)
{
// Found the specified observer in the list, delete it
m_ObserverList.erase(iter);
return;
}
}
}
void cButtonManager::NotifyObservers(void)
{
list<IObserver*>::iterator iter;
for (iter = m_ObserverList.begin(); iter != m_Observer开发者_StackOverflow中文版List.end(); ++iter)
{
(*iter)->Process(this);
}
}
For example, imagine that the list is a collection of people that subscribe to a magazine and the Process()
function is the delivery of a new magazine issue; if the magazines latest issue is awful the subscriber may wish to un-subscribe as a direct result of that issue.
Edit:
Some people in comments corrected me, so I will change this answer. But don't upvote, as it's the commenters' solution, not mine.
(*iter++)->Process();
I don't see why you are not using list::remove
here. That seems like a perfect match to me.
For the problem in NotifyObserver
I would not let Process
do the removing itself but rather let it signal that it wants itself to be removed from the list of observer. Plainly: return a bool from Process
to signal and then call list::erase
on it. Assign the return value of erase
to the current iter
.
精彩评论