使用 Visitor 时更改容器
我使用类似 STL 的迭代器在 C++ 中实现了访客模式,用于存储访客在容器中的当前位置。现在,我想在迭代容器时更改容器,并且我特别有兴趣从容器中删除项目,甚至是我当前正在访问的项目。
现在显然这将使 Visitor 内部迭代器无效,因为它正好指向这个项目。目前,我将所有迭代器的列表存储在容器中,并在列表中添加或删除任何内容后立即更新它们。因此在某种程度上,这类似于应用于迭代器(作为 Observer)和列表(作为 Observable)的观察者模式。
另外,我考虑让访问者()方法向访问者返回一些关于当前项目发生了什么以及如何继续迭代的提示,但这听起来也不是一个好主意,因为访问()实现不应该真的很关心找到下一个项目。
所以,我的问题是:即使将物品添加到容器中或从容器中删除,保持访问者工作的最佳方法是什么。
问候, Florian
更新:有一个访问者在容器上运行,但在 Visit() 方法内部,同一容器上可能会使用任意数量的附加迭代器。我希望访问者继续使用容器中的剩余项目,即使我们从调用 Visit() 返回后容器中的任何一项都被删除了。
I implemented the Visitor pattern in C++ using a STL-like iterator for storing the Visitor's current position in the container. Now I would like to change the container while I iterate over it, and I'm especially interested in deleting items from the container, even the one I'm currently visiting.
Now obviously this will invalidate the Visitors internal iterator, because it was pointing to exactly this item. Currently, I store a list of all iterators in the container and update them, as soon as anything is added to or removed from the list. So in a way this is similar to the Observer pattern applied to the iterator (as Observer) and the list (as Observable).
Alternatively I considered having the visitor() methods return some hint to the Visitor about what happend to the current item and how to proceed iterating, but that doesn't sound like such a good idea either, because the visit() implementation shouldn't really care about finding the next item.
So, my question is: What's the best way to keep a visitor working, even when items are added to the container or removed from it.
Regards,
Florian
Update: There's one visitor running over the container, but inside of the visit() method any number of additional iterators might be used on the same container. I want the visitor to continue with the remaining items in the container, even after we returned from a call to visit() in which any one of the items in the container got deleted.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当在遍历过程中改变容器时,迭代器充其量是危险的。使用索引并向后走是最安全的。
When mutating the container during traversal, iterators are hazardous, at best. It is safest to use an index and walk backwards.
我认为如果没有那么多迭代器和删除操作,您的(第一个)实现非常好。如果是这种情况,我会使用像 Eddy 推荐的类似标记和扫描的算法。另外,我认为后者更容易,因此更不容易出错。不要忘记跳过标记为删除的节点。
另一方面,如果除了“删除”之外还有其他情况需要更新迭代器,请坚持使用当前的实现。
I think your (first) implementation is pretty good if there are not so many iterators and delete operations. If this would be the case I would use a mark and sweep like algorithm like Eddy recommended. Also, I think the latter is easier and thus less error prone. Don't forget to skip nodes which are marked for deletion.
On the other hand, if there are cases besides 'delete' where your iterators need to be updated, stick to your current implementation.
在这些情况下,如果复制我的容器并不昂贵,我只需复制它并迭代该副本。原始容器通过shared_ptr保存对象,而副本仅保存weak_ptr。
In these cases, if copying my container is not expensive, I just copy it and iterate on the copy. The original container holds objects by shared_ptr while the copy just holds weak_ptr.