在下面的示例中,std :: list存储Resource类型的对象(按值,不指向)。 Resource类不提供小于比较也不提供相等运算符。通过标识(也称为内存地址)删除对象的好方法是什么。我可以以某种方式避免O(n)吗? std :: list是否是正确的容器?
// Definition of the container
std::list<Resource> resources;
// Code
Resource *closedResource = resourceFromList();
for (std::list<Resource>::iterator it = resources.begin(); it != resources.end(); ++it)
{
if (closedResource == &*it)
{
resources.erase(it);
break;
}
}
编辑:假设Resource类实现了移动语义。此外,资源会通过一种选择器(cp.epoll或java.nio.Selector)为事件通知重新注册任何“移动”。
答案 0 :(得分:2)
您将Resource
个副本存储在容器中,因此稍后按地址查找元素没有多大意义。
您可以做的是保存list::iterator
,因为list
具有以下属性:任何操作都不会使迭代器无效,从而明确擦除迭代器(或清除整个list
)。
答案 1 :(得分:1)
编辑:抱歉,不要理会这个答案 - 如果您确定只删除最多一个元素,那么您的循环就可以了。
不管是通过内存地址进行比较是否合理,但是在循环中使用list::erase
,您必须稍微改写它以避免增加无效的迭代器:
for (std::list<Resource>::iterator it = resources.begin(); it != resources.end(); )
{
if (want_to_erase) it = resources.erase(it); // advances to the next position
else ++it;
}
如果您没有其他要求而不是按地址查询,则可以始终只生成std::set
或std::unordered_set
个元素,并将Resource::operator<()
实现为指针比较。
无论哪种方式,它们都有某些条件可以作为STL容器成员;正如评论中所述,这些条件是否适用于您的Resource
课程?否则你可以只创建一个std::shared_ptr<Resource>
的容器并使用它内置的比较器,例如制作一个std::unordered_set<std::shared_ptr<Resource>>
。
答案 2 :(得分:0)
“std :: list是正确的容器吗?”
我对此表示怀疑。如果此类不提供比较运算符,您仍可以自己提供
struct resourcecomparation {
const bool operator() (const Resource &l, const Resource &r) const;
}resourcecomparator;
然后您可以使用std::set<resource, resourcecomparator>
。