如何在不删除C++集中删除项目?



使用std::set in C++,我能找到从集合中删除项目的唯一方法是使用 erase 方法。这将删除有问题的项目,我不希望发生这种情况。我能想到的从集合中删除项目而不删除它的唯一方法是创建一个新集合并迭代地将旧集合的所有项目添加到其中,确保不添加需要从集合中删除的项目,然后删除旧集合。

有没有更清洁的方法可以做到这一点?

如果不删除项目,则无法从集合中删除项目。集拥有其成员。如果从集合中删除该成员,则它不再存在。如果您希望能够删除某些内容而不删除它,请不要将其添加到集合中。

想象一下,如果你有int x[5]; x[2]=2;.如何才能x[2]脱离阵列?这甚至意味着什么?当然,您可以构造一个具有相同值的新整数,int j = x[2];.但这是一个新对象(具有相同的值),不会延长现有对象的生存期。

根据你的外部问题是什么,可能会有一个解决方案。例如,您可以将对象的std::unique_ptr添加到集合中,然后可以销毁该std::unique_ptr,而不会销毁它指向的对象,该对象正在构造同一基础对象的新std::unique_ptr

将对象移出集合

您可以使用extract从集合中删除相应的节点。这为您提供了节点的句柄。获得句柄后,您可以将项目移出句柄。

template<class T>
T find_and_remove(std::set<T>& s, T const& elem) {
auto iterator = s.find(elem); 
if(iterator == s.end() {
throw std::invalid_argument("elem not in set"); 
}
// Remove element, return node handle
auto node_handle = s.extract(iterator);
return std::move(node_handle.value());
}

或者,如果您已经拥有节点的迭代器,则可以像这样编写它:

template<class T>
T remove_from_set(std::set<T>& s, std::set<T>::iterator it) {
return std::move(s.extract(it).value());
}

移动值将转移该值拥有的任何资源的所有权。例如,如果集合包含字符串,则不会删除字符串的内容,并且字符串的任何迭代器都不会失效。

需要注意的是,如果你在集合中时有指向对象的指针或引用,这些将失效。

在不移动的情况下提取对象本身,并且不会使对对象的任何指针或引用无效

这是不太常见的情况,但如果你有指向集合中对象的引用或指针,则可能需要执行此操作。

同样,我们可以使用extract函数:

auto node_handle = s.extract(my_object);

或:

auto node_handle = s.extract(my_iterator); 

您可以使用node_handle.value()访问存储的对象,这将返回对该对象的引用。在删除node_handle之前,不会删除该对象,如果需要进一步延长其生存期,可以从函数返回node_handle,而无需删除该对象。

最新更新