挂钩到API时跟踪和存储对象的数据结构

时间:2014-04-02 03:36:31

标签: c++ data-structures map

我正在解决一个非常具体的问题,需要使用数据结构来存储和跟踪对象。使用一个简单的例子,假设我有以下两个类:

class Foo
{
    Foo Foo(bool isRed) {m_bRed = isRed} ;
    bool m_bRed;    
}

class Bar
{
    Bar Bar(Foo* pFoo) {m_pFoo = pFoo} ;
    Foo * m_pFoo;    
}

随着程序的运行,将会创建许多Foos和Bars,并且在程序终止时,我想知道有多少条是红色的(从它包含Foo)。请假设这两个类都没有getter / setter,解决这个问题的唯一方法就是挂钩Foo&Bar和构造函数。现在,做这个的最佳数据结构是什么?

我认为一个潜在的解决方案是使用以下格式的两张(无序)地图:

std::map<Foo*, bool> g_FooContainers;
std::map<Bar*, bool> g_BarContainers;

当创建Foo时,我们将其插入到地图中,

g_FooContainers.insert(std::make_pair(Foo*, isRed));

当创建Bar时,我们在其地图中查找传入的Foo *,如果找到,则将Bar插入其地图中并使用相应的isRed。

r = g_FooContainers.find(Foo*);
if (r != unordered_map::end) 
{
    g_BarContainers.insert(std::make_pair(Bar*, r->second)));
}

在程序执行结束时,我们可以遍历g_BooContainers并查看哪个Bar是红色的。

现在,我想知道是否有更有效的方法来做到这一点?也许只有一个std :: map?

请告诉我。

1 个答案:

答案 0 :(得分:0)

我建议:

  1. 保留一组Bar*
  2. Bar*添加到构造函数中的集合。
  3. 从析构函数中的集合中删除Bar*
  4. 最后,浏览Bar*集并从中收集Foo*集。我假设在没有删除带有指向它的Foo的情况下不会删除Bar。这可以确保如果有多个Bar指向同一个Foo,则您不会多次计算它。
  5. Foo*集进行迭代,并计算red的数量。
  6. 示例代码

    std::set<Bar*> g_aliveBars;
    
    class Bar
    {
       Bar(Foo* pFoo) {m_pFoo = pFoo; g_aliveBars.insert(this);}
       ~Bar() {g_aliveBars.erase(this);}
    
       Foo * m_pFoo;    
    }
    
    int getRedFoos()
    {
       std::set<Foo*> aliveFoos;
       for ( auto bar: g_aliveBars )
       {
          aliveFoos.insert(bar->m_pFoo);
       }
       int count = 0;
       for ( auto foo; aliveFoos)
       {
          count += (foo->m_bRed? 1 : 0);
       }
       return count;
    }
    

    如果没有类中的getter和setter,我希望您能提供一种机制来从Foo*获取Bar。您可以通过保留Boo* - &gt;的地图来实现这一目标。 Foo*。同样,您可以提供一种机制来回答Foo是否为红色。从本质上讲,您需要:

    std::map<Foo*, bool> g_FooIsRedMap;
    std::map<Bar*, Foo*> g_BarToFooMap;
    

    鉴于此,getRedFoos()可以翻译为:

    int getRedFoos()
    {
       std::set<Foo*> aliveFoos;
       for ( auto bar: g_aliveBars )
       {
          aliveFoos.insert(getFoo(bar));
       }
       int count = 0;
       for ( auto foo; aliveFoos)
       {
          count += (isRed(foo)? 1 : 0);
       }
       return count;
    }