Es gibt keine spezielle Eigenschaft der Sprache, die Ihnen dies ermöglicht. Manchmal wird die Objektverfolgung durch das Rollen des eigenen Speicherzuordners gehandhabt, aber dies funktioniert nicht einfach auf dem Stapel.
Wenn Sie jedoch nur den Stapel verwenden, wird Ihr Problem dadurch leichter, vorausgesetzt, dass die zu verfolgenden Objekte auf einem einzelnen Thread liegen. C++ gibt besondere Garantien über die Reihenfolge der Konstruktion und Zerstörung auf dem Stapel. Das heißt, die Zerstörungsreihenfolge ist genau umgekehrt zur Konstruktionsreihenfolge.
Und so können Sie dies verwenden, um einen einzelnen Zeiger in jedem Objekt zu speichern, plus einen statischen Zeiger, um den neuesten zu verfolgen. Jetzt haben Sie einen Objektstapel als verkettete Liste dargestellt.
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;
}
Beispiel:
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
}
Nun freilich ist dies eine sehr einfache Lösung. In einer großen Anwendung können Sie mehrere Stapel verwenden, die Ihre Objekte verwenden. Sie könnten Stacks in mehreren Threads verarbeiten, indem Sie current()
die Semantik thread_local verwenden. Obwohl Sie etwas Magie benötigen, um das zu funktionieren, müsste head()
auf eine Registrierung von Threads zeigen, und das würde Synchronisierung erfordern.
Sie auf jeden Fall do nicht alle Stapel in einer einzigen Liste synchronisiert werden sollen, denn das Ihr Programm Leistungsskalierbarkeit töten.
Für Ihre Pull-Anforderung nehme ich an, dass es ein separater Thread ist, der über die Liste gehen möchte. Sie würden eine Möglichkeit zur Synchronisierung benötigen, so dass alle neuen Objektkonstruktionen oder -zerstörungen innerhalb von Trackable<T>
blockiert werden, während die Liste iteriert wird. O.ä.
Aber zumindest könnte man diese Grundidee nehmen und auf Ihre Bedürfnisse erweitern.
Denken Sie daran, dass Sie diese einfache Liste nicht verwenden können, wenn Sie Ihre Objekte dynamisch zuweisen. Dafür benötigen Sie eine bidirektionale Liste.
Welche Art von Statistiken benötigen Sie? Wenn Sie nur die Anzahl der Live-Instanzen verfolgen, dann überlegen Sie, ob Sie eine einzelne atomare Ganzzahl pro Klasse speichern und vielleicht einen einfachen RAII-Wrapper zum Zählen erstellen (das heißt, Sie geben ihn einfach in Ihre Klassendefinition ein und die Arbeit ist erledigt). – paddy
Wenn es etwas nützt, [hier ist ein einfaches Beispiel] (http://coliru.stacked-crooked.com/a/5a25d7a6a2ec18a0) von dem, worüber ich gesprochen habe. Sie können Ihre Objekte nicht iterieren oder durchsuchen, aber es ist nicht klar, warum Sie das tun möchten. Es ist wahrscheinlich keine gute Idee, auf einen anderen Stack zuzugreifen. In diesem Beispiel werden Objektanzahlwerte mit sehr geringem Overhead und Thread-sicher bereitgestellt. – paddy
Das wäre im Grunde ein Push-Update, wird aber als zu teuer angesehen. – choeger