如何从容器中删除指针中的unique_ptr?

时间:2011-08-01 22:40:44

标签: c++11 unique-ptr

使用unique_ptr创建对象并为容器提供所有权是没有问题的。如何通过原始指针删除元素?

std::set<std::unique_ptr<MyClass>> mySet;

MyClass *myClass = new MyClass();
mySet.insert(std::unique_ptr<MyClass>(myClass));

// remove myClass from mySet?

5 个答案:

答案 0 :(得分:3)

您需要找到与myClass元素对应的迭代器,然后将该迭代器传递给mySet.erase()。可以使用std::find_if算法和自定义Predicate仿函数找到迭代器,该仿函数了解如何取消引用unique_ptr并将其与原始指针myClass进行比较。

您无法使用重载的size_t set::erase ( const key_type& x );,因为在unique_ptr中找不到原始指针(即使包含在临时mySet中)。

答案 1 :(得分:3)

不像我想的那么漂亮。但以下工作如下:

#include <memory>
#include <set>
#include <iostream>

struct do_nothing
{
    void operator()(const void*) const {}
};

struct MyClass
{
    MyClass() {std::cout << "MyClass()\n";}
    MyClass(const MyClass&) {std::cout << "MyClass(const MyClass&)\n";}
    ~MyClass() {std::cout << "~MyClass()\n";}
};

int main()
{
    std::set<std::unique_ptr<MyClass>> mySet;

    MyClass *myClass = new MyClass();
    mySet.insert(std::unique_ptr<MyClass>(myClass));

    // remove myClass from mySet?
    std::set<std::unique_ptr<MyClass>>::iterator i =
        lower_bound(mySet.begin(), mySet.end(),
                    std::unique_ptr<MyClass, do_nothing>(myClass));
    if (i != mySet.end() && *i == std::unique_ptr<MyClass, do_nothing>(myClass))
        mySet.erase(i);
}

答案 2 :(得分:1)

我似乎能够使用带有lower_bound的自定义谓词来检索迭代器。由于std :: set是一个有序容器,因此lower_bound应该以对数方式执行。

std::set<std::unique_ptr<MyClass>>::iterator i =
    std::lower_bound(mySet.begin(), mySet.end(), myClass, MyPredicate<MyClass>());

template<class Type>
struct MyPredicate
{
    bool operator()(const std::unique_ptr<Type>& left, const Type* right) const
    {
        return left.get() < right;
    }
}

答案 3 :(得分:0)

仍然不是最佳解决方案,但目前我选择:

PointerMap<MyFoo>::Type myFoos;

MyFoo * myFoo = new MyFoo();
myFoos.insert(PointerMap<MyFoo>::Item(myFoo));

标题是:

#include <map>
#include <memory>
#include <utility>

template<typename T>
struct PointerMap
{
    typedef std::map<T *, std::unique_ptr<T>> Type;

    struct Item : std::pair<T *, std::unique_ptr<T>>
    {
        Item(T * pointer)
            : std::pair<T *, std::unique_ptr<T>>(pointer, std::unique_ptr<T>(pointer))
        {
        }
    };
};

答案 4 :(得分:0)

您可能会喜欢这里的答案:Efficiently erase a unique_ptr from an unordered_set

这是针对C ++ 14的,但我认为也适用于C ++ 11。

这不是很漂亮,但是却做得很有效–无需扫描容器,而是使用适当的基于哈希的查找。