【发布时间】:2013-10-07 09:24:17
【问题描述】:
我想知道这是否是一种可接受的做法:
struct Item { };
std::list<std::shared_ptr<Item>> Items;
std::list<std::shared_ptr<Item>> RemovedItems;
void Update()
{
Items.push_back(std::make_shared<Item>()); // sample item
for (auto ItemIterator=Items.begin();ItemIterator!=Items.end();ItemIterator++)
{
if (true) { // a complex condition, (true) is for demo purposes
RemovedItems.push_back(std::move(*ItemIterator)); // move ownership
*ItemIterator=nullptr; // set current item to nullptr
}
// One of the downsides, is that we have to always check if
// the current iterator value is not a nullptr
if (*ItemIterator!=nullptr) {
// A complex loop where Items collection could be modified
}
}
// After the loop is done, we can now safely remove our objects
RemovedItems.clear(); // calls destructors on objects
//finally clear the items that are nullptr
Items.erase( std::remove_if( Items.begin(), Items.end(),
[](const std::shared_ptr<Item>& ItemToCheck){
return ItemToCheck==nullptr;
}), Items.end() );
}
这里的想法是我们正在标记项目容器可能会受到外部来源的影响。当从容器中删除一个项目时,它只是设置为 nullptr 但在此之前移动到 RemovedItems。
事件之类的东西可能会影响Items 并添加/删除项目,所以我必须想出这个解决方案。
这看起来是个好主意吗?
【问题讨论】:
-
这应该是类似于垃圾收集器的东西,稍后会删除这些项目吗?将其移至另一个列表并稍后将其删除,而不是直接删除它有什么好处?
-
@itwasntpete 本质上,我总是知道何时删除我的对象(在循环之后)。
-
当您说“可能受到外部来源的影响”时,您是什么意思?你的目标是在循环之后删除东西,而不是在循环期间?为什么?
-
@doctorlove 想想
Root->Parent->Child关系。可能会在Child中触发一个事件,该事件可能会从Root中删除Parent。所以循环可能会在中间中断,迭代器将无效。 -
我还是不明白你在保护什么。您的意思是销毁
Item对象之一可能会导致其他项目从列表中删除?或者你的意思是另一个线程可能会在你迭代列表时修改它?您的解决方案可以防止第一个,但如果其他线程正在修改列表,则无济于事。
标签: c++ list c++11 vector erase-remove-idiom