我应该如何在工厂类中存储弱指针列表?



我的项目中有一个工厂类,如果调用Create方法,它将返回std::shared_ptr<MyClass>。工厂不是所有者,但它维护已创建对象的列表。有时工厂需要遍历仍在使用的已创建对象,或对它们进行计数。

我使用std::vector<std::weak_ptr<MyClass>>实现了这一点。迭代如下所示:

for (std::weak_ptr<MyClass> wp : weak_list) {
if (auto sp = wp.lock()) {
//..
}
}

Create功能:

std::shared_ptr<MyClass> Create(/* ... */) {
std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();
//...
weak_list.push_back(obj);
return obj;
}

矢量是此类列表的最佳容器吗?也许std::set会更好。

如果我使用向量实现这一点,我必须定期检查列表中的过期指针并删除它们

在工厂类中存储弱指针列表的首选方法是什么?

默认情况下使用向量。

集合不会自行清洁过期指针,手动清洁过程相同。

考虑在迭代之前清理死元素,并迭代弱列表的副本(以防迭代改变弱列表(。

如果需要立即清理悬空的弱 ptrs,请修改共享 ptr,以便在最后一个强引用消失时从弱列表中注销自身。 这需要一些工作来做共享,包括对齐的存储、手动构造和销毁、辅助结构和共享 ptr 的别名构造器。

template<class T>
struct shared_helper {
typename std::aligned_storage<sizeof(T),alignof(T)::type data;
T* get(){ return reinterpret_cast<T*>(&data); }
bool constructed = false;
weak_list<T>* list=0;
std::weak_ptr<T> self;
~shared_helper(){
if (constructed){
get()->~T();
constructed=false;
}
if (list) list->erase(self);
}
template<class...Ts>
T* emplace(Ts&&...ts){
T* r = ::new( (void*)&data ) T(std::forward<Ts>(ts)...);
constructed = true;
return r;
}
};
template<class T, class...Args>
std::shared_ptr<T> make_and_register( weak_list<T>& list, Args&&...args ){
auto r = std::make_shared<shared_helper<T>>();
if(!r) return {};
r->emplace( std::forward<Args>(args)... );
std::shared_ptr<T> ptr( r, r->get() );
r->self = ptr;
list.insert(ptr);
r->list = &list
return ptr;
}

这有点迟钝,未经测试和编译。 但在这种情况下,弱列表的集合或无序集合是有意义的,因为我们使用快速查找在最后一个强引用过期时立即清理弱列表。

最新更新