簡體   English   中英

如何在不刪除C ++的集合中刪除項目?

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

在C ++中使用std :: set,我可以找到從集合中刪除項目的唯一方法是使用erase方法。 這會刪除有問題的項目,我不希望這樣做。 我可以想到從一個集合中移除一個項目而不刪除它的唯一方法是創建一個新集合並迭代地將舊集合的所有項目添加到它中,確保不添加需要從中刪除的項目集合,然后刪除舊集。

有更清潔的方法嗎?

您無法刪除集合中的項目而不刪除它。 設置自己的成員。 如果從集合中刪除該成員,則該成員不再存在。 如果您希望能夠刪除某些內容而不刪除它,請不要將其添加到集合中。

想象一下,如果你有int x[5]; x[2]=2; 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而不刪除該對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM