跟踪(堆栈分配的)对象

cho*_*ger 6 c++ pointers global reference

在一个相当大的应用程序中,我想跟踪一些关于某个类的对象的统计信息.为了不降低性能,我希望在拉配置中更新统计数据.因此,我需要在某个位置引用每个活动对象.是否有惯用的方式:

  1. 创建,搜索,迭代此类引用
  2. 自动管理(即在销毁时删除参考)

我在这里考虑一组智能指针,但是内存管理会有些颠倒:当智能指针被销毁时,我不想破坏对象,当对象被销毁时我想要移除智能指针.理想情况下,我不想重新发明轮子.

我可以延迟删除指针,我只需要一种方法来快速使它们失效.

编辑:因为稻田要求它:基于拉动的收集的原因是获取信息可能相对昂贵.推动显然是一个干净的解决方案,但被认为太昂贵.

pad*_*ddy 2

该语言没有任何特殊功能可以让您执行此操作。有时对象跟踪是通过滚动您自己的内存分配器来处理的,但这在堆栈上并不容易工作。

但是,如果您仅使用堆栈,它实际上会使您的问题变得更容易,假设被跟踪的对象位于单个线程上。C++ 对堆栈上构造和销毁的顺序做出了特殊保证。也就是说,销毁顺序与构造顺序正好相反。

因此,您可以利用它在每个对象中存储一个指针,再加上一个静态指针来跟踪最近的一个。现在您有了一个表示为链接列表的对象堆栈。

template <typename T>
class Trackable
{
public:
    Trackable()
    : previous( current() )
    {
        current() = this;
    }

    ~Trackable()
    {
        current() = previous;
    }

    // External interface
    static const T *head() const { return dynamic_cast<const T*>( current() ); }
    const T *next() const { return dynamic_cast<const T*>( previous ); }

private:
    static Trackable * & current()
    {
        static Trackable *ptr = nullptr;
        return ptr;
    }

    Trackable *previous;
}
Run Code Online (Sandbox Code Playgroud)

例子:

struct Foo : Trackable<Foo> {};
struct Bar : Trackable<Bar> {};

//  :::

// Walk linked list of Foo objects currently on stack.
for( Foo *foo = Foo::head(); foo; foo = foo->next() )
{
    // Do kung foo
}
Run Code Online (Sandbox Code Playgroud)

现在,无可否认,这是一个非常简单的解决方案。在大型应用程序中,您可能有多个使用对象的堆栈。您可以通过使用current()thread_local 语义来处理多个线程上的堆栈。尽管您需要一些魔法才能完成这项工作,因为head()需要指向线程注册表,并且这需要同步。

您绝对不想将所有堆栈同步到单个列表中,因为这会破坏程序的性能可扩展性。

至于您的拉动要求,我认为这是一个想要遍历列表的单独线程。您需要一种同步方法,以便Trackable<T>在迭代列表时所有新对象的构造或销毁都被阻止在内部。或者类似的。

但至少您可以采用这个基本想法并将其扩展到您的需求。

请记住,如果动态分配对象,则无法使用这种简单的列表方法。为此,您需要一个双向列表。