简体   繁体   English

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

[英]How can I remove an item from a set in C++ without deleting it?

Using std::set in C++, the only way I can find to remove an item from a set is to use the erase method. 在C ++中使用std :: set,我可以找到从集合中删除项目的唯一方法是使用erase方法。 This deletes the item in question, which I don't want to happen. 这会删除有问题的项目,我不希望这样做。 The only way I can think of to remove an item from a set without deleting it would be to create a new set and add all the items of the old set to it iteratively, making sure to not add the item that needs to be removed from the set, then deleting the old set. 我可以想到从一个集合中移除一个项目而不删除它的唯一方法是创建一个新集合并迭代地将旧集合的所有项目添加到它中,确保不添加需要从中删除的项目集合,然后删除旧集。

Is there a cleaner way to do this? 有更清洁的方法吗?

You can't remove an item from a set without deleting it. 您无法删除集合中的项目而不删除它。 Sets own their members. 设置自己的成员。 If the member is removed from the set, it doesn't exist anymore. 如果从集合中删除该成员,则该成员不再存在。 If you want to be able to remove something without deleting it, don't add it to a set. 如果您希望能够删除某些内容而不删除它,请不要将其添加到集合中。

Imagine if you have int x[5]; x[2]=2; 想象一下,如果你有int x[5]; x[2]=2; int x[5]; x[2]=2; . How can you get x[2] out of the array? 怎么能从阵列中得到x[2] What would that even mean? 这甚至意味着什么? You can, of course, construct a new integer with the same value, int j = x[2]; 当然,您可以构造一个具有相同值的新整数, int j = x[2]; . But that's a new object (with the same value) that is not extending the life of the existing object. 但这是一个新的对象(具有相同的值),不会延长现有对象的寿命。

Depending on what your outer problem is, there might be a solution. 根据您的外部问题,可能有一个解决方案。 For example, you could add a std::unique_ptr to an object into a set and then you can destroy that std::unique_ptr without destroying the object it points to be constructing a new std::unique_ptr to the same underlying object. 例如,您可以将一个std::unique_ptr添加到一个集合中,然后您可以销毁该std::unique_ptr而不会破坏它指向为同一个底层对象构造一个新的std::unique_ptr的对象。

Moving an object out of a set 将对象移出集合

You can use extract to remove the corresponding node from the set. 您可以使用extract从集合中删除相应的节点。 This gives you a handle to the node. 这为您提供了节点的句柄。 Once you have the handle, you can move the item out of the handle. 拿到手柄后,可以将物品移出手柄。

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());
}

Alternatively, if you already have the iterator to the node, you can write it like this: 或者,如果您已经拥有节点的迭代器,则可以这样写:

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

Moving the value transfers ownership of any resources owned by the value. 移动该值会转移该值所拥有的任何资源的所有权。 For example, if the set contains a string, the contents of the string won't be deleted, and any iterators to the string won't be invalidated. 例如,如果集合包含字符串,则不会删除字符串的内容,并且不会使字符串的任何迭代器失效。

The caveat of this is that if you had pointers or references to the object from when it was still in the set, these will be invalidated. 需要注意的是,如果你在对象中有指针或引用,那么它们将无效。

Extracting the object itself without a move and without invalidating any pointers or references to the object 无需移动即可提取对象本身,并且不会使任何指针或对对象的引用无效

This is the less common case, but if you had a reference or pointer to the object in the set, you may want to do this. 这是不太常见的情况,但如果你有一个引用或指向集合中对象的指针,你可能想要这样做。

Again, we can use the extract function: 同样,我们可以使用extract功能:

auto node_handle = s.extract(my_object);

Or: 要么:

auto node_handle = s.extract(my_iterator); 

You can access the stored object with node_handle.value() , which returns a reference to the object. 您可以使用node_handle.value()访问存储的对象,该对象返回对该对象的引用。 The object won't be deleted until the node_handle is deleted, and if you need to extend it's lifetime further, you can return the node_handle from a function without the object being deleted. 在删除node_handle之前,不会删除该对象,如果需要进一步延长它的生命周期,则可以从函数返回node_handle而不删除该对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM