使用 unique_ptr 创建对象并赋予容器所有权是没有问题的。如何通过原始指针删除元素?
std::set<std::unique_ptr<MyClass>> mySet;
MyClass *myClass = new MyClass();
mySet.insert(std::unique_ptr<MyClass>(myClass));
// remove myClass from mySet?
使用 unique_ptr 创建对象并赋予容器所有权是没有问题的。如何通过原始指针删除元素?
std::set<std::unique_ptr<MyClass>> mySet;
MyClass *myClass = new MyClass();
mySet.insert(std::unique_ptr<MyClass>(myClass));
// remove myClass from mySet?
您将需要找到与该myClass
元素对应的迭代器,然后将该迭代器传递给mySet.erase()
. 可以使用std::find_if
带有自定义Predicate
仿函数的算法找到迭代器,该仿函数了解如何取消引用unique_ptr
并将其与原始指针进行比较myClass
。
您不能使用重载size_t set::erase ( const key_type& x );
,因为unique_ptr
在mySet
.
没有我想要的那么漂亮。但以下工作:
#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);
}
看来我能够使用带有 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;
}
}
仍然不是最好的解决方案,但目前我选择:
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))
{
}
};
};
您可能会喜欢这里的答案:Efficiently erase a unique_ptr from an unordered_set
这适用于 C++14,但我认为也适用于 C++11。
它不漂亮,但效率很高——不扫描容器,而是使用适当的基于哈希的查找。