【问题标题】:Store pointers to objects in multiple containers在多个容器中存储指向对象的指针
【发布时间】:2013-02-07 06:24:54
【问题描述】:

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

                                {p1, p2, ..., pn} 

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

【问题讨论】:

  • 是的,使用std::shared_ptr
  • 不,shared_ptr 不能解决问题。我仍然需要去两个容器来尊重 shared_ptr 才能删除对象。这是不可取的。我想要这样的东西,如果我删除容器 A 中的指针,容器 B 中的相同指针将被自动删除。

标签: c++ algorithm data-structures containers


【解决方案1】:

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

  • 重新设计整个对象架构,使指针不在许多容器中。
  • 使用Boost Multi-index Containers Library 在一个容器中实现您想要的所有功能。
  • 使用映射键而不是直接指针来跟踪对象,并将指针本身保留在一个映射中。
  • 使用std::weak_ptr,这样您就可以检查项目是否已在其他地方删除,并在使用时将其转为std::shared_ptr(您需要一个容器拥有“master”std::shared_ptr,以便在不使用时保留对象)
  • 创建函数/方法/类来删除对象,它知道所有容器,所以当所有删除都在一个地方时,您不会意外忘记。

【讨论】:

  • 是的,你的理解是对的。我投了赞成票,但想把这个问题留待更长时间。谢谢。
  • 是的,在 SO 上不要过早接受答案是明智之举。为可能的 Boost 解决方案添加了一个项目符号。
【解决方案2】:

您为什么不创建自己的包含std::liststd::unordred_map 的类,并提供访问功能并提供删除功能,您可以使用list 线性访问它们,并使用@ 随机访问它们987654324@,删除将从两个容器中删除,插入将插入到两个容器中。 (一种包装类:P)

您还可以考虑使用std::map,并为其提供比较功能,这将始终保持您的数据结构以所需的方式排序,您还可以使用log N 随机访问元素访问时间。

【讨论】:

    【解决方案3】:

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

    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 来保持指针同步。

    【讨论】:

      【解决方案4】:

      如果我正确理解您的问题,您对内存管理(新/删除问题)的关注较少,而对哪个元素有效与否的实际“簿记”更为关注。

      所以,我正在考虑用“参考计数器”包装每个点

       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;
       };
      

      【讨论】:

        【解决方案5】:

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

        无论如何,您可能更喜欢使用Boost Multi-index Containers Library

        【讨论】:

          猜你喜欢
          • 2010-09-13
          • 2014-12-19
          • 2021-05-20
          • 2014-04-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多