【问题标题】:Data structure to track and store objects when hooking into APIs挂钩 API 时跟踪和存储对象的数据结构
【发布时间】:2014-04-02 03:36:30
【问题描述】:

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

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

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

在程序运行时,将创建许多 Foo 和 Bars,并且在程序终止时,我想知道有多少 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 被创建时,我们在它的 map 中查找传入的 Foo*,如果找到,将 Bar 插入到它的 map 中,并带有对应的 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?

请告诉我。

【问题讨论】:

  • 添加 getter 和 setter 似乎是一个更好的解决方案,因为您已经有了一个集合。您似乎只是在复制集合以存储更多数据。如果它们不同步,上帝会帮助你......另一种方法取决于你的需要:只需保留一个 int 的 redFooCount 并在创建时递增,在销毁时递减。

标签: c++ data-structures map


【解决方案1】:

我要建议:

  1. 保留一组Bar*
  2. Bar* 添加到构造函数中的集合中。
  3. 从析构函数的集合中移除Bar*
  4. 最后,遍历Bar* 的集合并从中收集Foo* 的集合。我假设Foos 不会在不删除具有指向它的指针的Bars 的情况下被删除。这样可以确保如果有多个 Bars 指向同一个 Foo,您不会多次计算。
  5. 遍历Foo* 的集合并计算red 的数量。

示例代码

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,我希望你能提供一种机制来从 Bar 获取 Foo*。您可以通过保留Boo* -> 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;
}

【讨论】:

  • 这实际上违反了类没有 getter/setter 的前提。这实际上不是我强加的人为条件。实际上,Foo 和 Bar 是对象的不透明句柄,我不知道如何从 Bar 中检索 Foo。更详细地说,当我创建 Foo 或 Bar 时,创建函数看起来更像这样“CreateFoo (FooDescriptor desc, Foo** pFoo)”和“CreateBar (BarDescriptor desc, Bar** pBar)”
  • @lancery,当然你不希望类中的 getter 和 setter。您是否反对提供通过另一种机制获取Foo* from Bar` 并查询Foo 是否为红色的能力?如果你不反对,你可以使用我建议的核心。
  • 并不是我反对它,只是不可能,因为这些对象的构造函数(即 CreateFoo 和 CreateBar)只返回不透明的对象句柄,所以我无法从 Bar* 获取 Foo*并查询 Foo* 是否为红色。这就是我以这种方式表述简化示例的原因。
  • 您希望如何获得在您发布的代码中使用的isRedFoo*
  • “IsRed”是在 Foo 的构造函数期间传入的参数,这是我可以访问该信息的唯一地方,所以这就是 Foo* 被添加到其映射中的地方。至于 Foo*,同样是 Bar 的构造函数等传入的参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多