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

How should I store a list of weak pointers in the factory class?

我的项目中有一个Factoryclass,如果调用了Create方法,就是returnsstd::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;
}

vector 是像这样的列表的最佳容器吗?也许 std::set 会更好。

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

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

默认使用矢量。

Sets不会自行清理过期指针,手动清理过程相同。

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

如果您需要立即清除悬挂的弱指针,请修改共享指针以在最后一个强引用消失时从弱列表中注销自身。这需要一些与 make shared 有关的工作,包括对齐存储、手动构建和销毁、辅助结构和共享 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;
}

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