将指向对象的指针存储在多个容器中

Store pointers to objects in multiple containers

本文关键字:存储 对象 指针      更新时间:2023-10-16

为了提出我的问题,让我们假设我有一组指针(相同类型)

                                {p1, p2, ..., pn} 

我想将它们存储在多个容器中,因为我需要不同的访问策略来访问它们。假设我想将它们存储在两个容器中,链表和哈希表。对于链表,我有顺序,对于哈希表,我有快速访问。现在,问题是,如果我从一个容器中删除指针,我需要记住从另一个容器删除。这使得代码难以维护。所以问题是,是否有其他模式或数据结构来管理这种情况?智能指针在这里有用吗?

如果我理解正确,您希望链接您的容器,以便从一个容器中删除从所有容器中删除。我不认为这是直接可能的。可能的解决方案:

  • 重新设计整个对象体系结构,所以指针不在很多容器中
  • 使用Boost多索引容器库可以在一个容器中实现所需的所有功能
  • 使用贴图关键点而不是直接指针来跟踪对象,并将指针本身保持在一个贴图中
  • 使用std::weak_ptr,这样您就可以检查项目是否已在其他地方删除,并在使用时将其转换为std::shared_ptr(您需要一个容器来拥有"主"std::shared_ptr,以便在不使用时保留对象)
  • 创建函数/方法/类来删除对象,它知道所有容器,所以当所有删除都在一个地方时,你不会意外忘记

为什么不创建自己的类,它包含std::liststd::unordred_map,并提供访问函数和删除函数,这样您就可以用list线性访问它们,用unordred_map随机访问它们,删除将从两个容器中删除,插入将插入到两个容器。(某种包装类:P)

此外,您还可以考虑使用std::map,并为其提供一个比较函数,该函数将始终以所需的方式保持数据结构的有序性,并且您还可以使用log N访问时间随机访问元素。

与往常一样,尝试隔离此逻辑以使其更易于支持。一些具有安全公共接口的小类(对不起,我没有编译这个,它只是一个伪代码)。

template<class Id, Ptr>
class Store
{
public:
   void add(Id id, Ptr ptr)
   {
      m_ptrs.insert(ptr);
      m_ptrById.insert(std::make_pair(id, ptr));
   }
   void remove(Ptr ptr)
   {
      // remove in sync as well
   }
private:
   std::list<Ptr> m_ptrs;
   std::map<Id, Ptr> m_ptrById;
};

然后使用Store来保持指针的同步。

如果我正确理解您的问题,那么您不太关心内存管理(新/删除问题),而更关心哪个元素有效与否的实际"记账"。

所以,我想用一个"参考计数器"来包装每个点

 template< class Point >
 class BookKeeping {
 public:
     enum { LIST_REF = 0x01,
            HASH_REF = 0x02 };
     BookKeeping( const Point& p ): m_p(p), m_refCout( 0x3 ) {} // assume object created in both containers
     bool isValid() const { return m_refCount == 0x3; } // not "freed" from any container
     void remove( unsigned int from ) { m_refCount = m_refCount & ! from ; }
 private:
     Point m_p;
     unsigned int m_refCount;
 };

看看这个类似问题的答案(目前是唯一的答案)。在这种情况下,建议使用deque而不是list,因为OP只想在序列的末尾插入/删除。

无论如何,您可能更喜欢使用Boost多索引容器库。