Adresse einer statischen Variable

9

Ich versuche eine einfache Klasse für die eindeutige ID-Konvertierung zu erstellen. Ich denke darüber nach, eine statische Methode hinzuzufügen:

%Vor%

Jede Klasse würde dann durch das eindeutige int const * identifiziert werden. Funktioniert das garantiert? Ist der zurückgegebene Zeiger wirklich eindeutig? Gibt es eine bessere, einfachere Lösung?

Ich habe auch über den Zeiger auf std::type_info nachgedacht:

%Vor%

Ist das besser?

Bearbeiten:

Ich muss die ID nicht für die Serialisierung verwenden. Ich möchte nur eine kleine Menge von Basisklassen identifizieren und ich möchte, dass alle Unterklassen einer Klasse die gleiche ID haben

    
Juraj Blaho 23.09.2011, 08:00
quelle

9 Antworten

2

Wie ich zumindest bemerkt habe, optimiert MSVC 2008 oder 2010 die statische Variable, so dass die folgende Funktion GetId dieselbe Adresse auch für verschiedene Klassen zurückgibt.

%Vor%

Daher kann die Adresse der nicht initialisierten konstanten statischen Variablen nicht zur Identifikation verwendet werden. Die einfachste Lösung ist das Entfernen von const :

%Vor%

Eine andere Lösung zum Generieren von IDs, die scheinbar funktioniert, ist die Verwendung einer globalen Funktion als Zähler:

%Vor%

Und dann definieren Sie die folgende Methode in den zu identifizierenden Klassen:

%Vor%

Da die zu definierende Methode immer dieselbe ist, kann sie in eine Basisklasse eingefügt werden:

%Vor%

Und dann verwenden Sie ein seltsam wiederkehrendes Muster:

%Vor%     
Juraj Blaho 06.10.2011, 13:25
quelle
8

Ja, das wird funktionieren. Jedes static local erhält zu dem Zeitpunkt, zu dem das Modul geladen wird, einen eindeutigen Speicherort, und es bleibt bestehen, bis das Modul entladen wird. Denken Sie daran, static localhosts werden in statischem Speicher gespeichert, der während der Kompilierung verteilt wird, und sie bleiben bestehen, bis das Modul entladen wird, sodass sie unterschiedliche Speicherorte haben.

    
sharptooth 23.09.2011 08:06
quelle
6

Die Adresse der statischen Variable ist garantiert eindeutig und in allen Übersetzungseinheiten gleich.

Es ist keine gute Idee, weil Sie Code zu jeder zu identifizierenden Klasse hinzufügen müssen.

Die Zeiger auf Typ-Info-Objekte sind nicht garantiert eindeutig, aber die Typ-Info-Objekte selbst werden garantiert als gleich für eine gegebene Klasse verglichen und als ungleich für verschiedene Klassen. Dies bedeutet, dass Sie kleine Wrapper-Objekte verwenden können, die Typ-Info-Zeiger enthalten, und die Vergleiche mit den Typ-Info-Objekten delegieren. C ++ 11 hat einen solchen Wrapper in der Standardbibliothek, und wenn Sie keinen Zugriff darauf haben, gibt es einen in Andrei Alexandrescus "Modern C ++ Design", und deshalb wahrscheinlich auch in der Loki-Bibliothek, in der es wahrscheinlich einen gibt Boost, und es gibt einen auf meinem Wordpress-Blog - es ist nicht so, als hättest du einen von Grund auf neu erfunden.

Wenn die IDs jedoch für die Serialisierung verwendet werden sollen, benötigen Sie IDs, die für Builds gültig sind. Und in diesem Fall brauchen Sie Strings oder UUIDs. Ich würde mit UUIDs gehen.

Um eine Klasse mit einer UUID zu verbinden, können Sie im Allgemeinen eine Typ-Traits-Klasse verwenden. Oder wenn Sie nur Windows-Programmierung durchführen, können Sie dafür die Spracherweiterungen von Visual C ++ verwenden. Ich denke aber ich bin nicht 100% sicher, dass diese Spracherweiterungen auch von g ++ (in Windows) implementiert werden.

Prost & amp; hth.

    
Cheers and hth. - Alf 23.09.2011 08:17
quelle
2

Die Adresse der statischen int ist garantiert für jede eindeutig Funktion (und das gleiche für jeden Aufruf der gleichen Funktion). So wie, Es kann sehr gut als ID innerhalb einer einzigen Ausführung des Codes arbeiten. Die Adresse könnte sich möglicherweise von einem Lauf zum nächsten ändern und wird dies auch tun oft von einer Zusammenstellung zur nächsten wechseln (wenn Sie sich geändert haben alles im Code), also ist es keine gute Lösung für eine externe ID. (Sie sagen nicht, ob die ID außerhalb einer einzigen Ausführung gültig sein muss oder nicht.)

Die Adresse der Ergebnisse eines typeid ist nicht garantiert Gleiches jedes Mal, wenn Sie die Funktion aufrufen (obwohl es wahrscheinlich sein wird). Sie könnten es jedoch verwenden, um einen Zeiger zu initialisieren:

%Vor%

Im Vergleich zur Verwendung von int* hat dies den Vorteil, zusätzliche Funktionen bereitzustellen Informationen (z. B. zum Debuggen). Wie int* , kann der Bezeichner sein verschieden von einem Lauf zum nächsten; A::GetId()->name() zeigt auf die gleiche Zeichenfolge '%code%' beendet (obwohl die Adresse möglicherweise erneut lautet) anders) vorausgesetzt, Sie kompilieren mit dem gleichen Compiler. (Soweit ich Kann sagen, der Standard garantiert das nicht, aber in der Praxis denke ich Sie sind sicher.) Ändern Sie Compiler, und alle Wetten sind aus.

Die Lösung, die ich in der Vergangenheit verwendet habe, ist etwa:

%Vor%

Dies bietet eine eindeutige Kennung, die leicht verglichen werden kann Ausführung des Codes und ein Zeichenfolgenwert, der als externe Kennung, und das ist über alle Compiler gewährleistet. Wir implementiert dies als ein Makro, das sowohl die statische Funktion definiert, und eine virtuelle Funktion, die sie zurückgab, z.B.:

%Vor%

Dies führt zu einer sehr schnellen (aber begrenzten) RTTI und unterstützt externe Identifikatoren für Serialisierung und Persistenz.

    
James Kanze 23.09.2011 08:22
quelle
1

Die int * -Methode wäre eindeutig, da für jede statische Variable eine andere statische Speicherzelle zugewiesen werden müsste, und ich denke, es ist einfacher zu verstehen als die Idee von type_info.

    
thiton 23.09.2011 08:07
quelle
1

Offensichtlich müssen Zeiger auf verschiedene Variablen unterschiedliche Werte haben. Achten Sie nur darauf, wenn Sie eine Unterklasse von A ableiten. Sie müssen entscheiden, was Ihre Richtlinie für die ID ist. Wenn Sie nichts tun, dann hätte die Unterklasse dieselbe ID.

    
David Heffernan 23.09.2011 08:10
quelle
0

Im Allgemeinen wollen Sie wirklich solche Hacky-Sachen vermeiden. Wenn ich das wirklich tun müsste, würde ich ein UUID-System verwenden (es gibt eine Boost-Bibliothek dafür, aber ich bin nicht sehr damit vertraut), oder ein Singleton, das eine Liste dieser Objekte zu welchem ​​Zweck auch immer pflegte Sie brauchen.

    
Ayjay 23.09.2011 08:09
quelle
0

Statische Variablen werden initialisiert, bevor Heap & amp; Stapelspeicher, also ja, es wird einzigartig sein.

Quirky though.

    
Valmond 23.09.2011 08:07
quelle
-1

Da Sie diese Methode allen Klassen hinzufügen müssen, die eine UID benötigen, können Sie dies auch tun.

%Vor%

Der Vorteil davon ist, dass der Compiler eine Sprungtabelle verwenden kann, wenn Sie diese für RTTI zum Einschalten verwenden, was mit zwei Zeigern nicht möglich ist, weil die Sprungtabelle sehr spärlich wäre. p>

Der (kleinere) Nachteil besteht darin, dass Sie verfolgen müssen, welche Identifikatoren verwendet wurden.

Ein großer Nachteil der ersten von Ihnen vorgestellten Methode besteht darin, dass die gleichen Zahlen nicht zur Identifizierung von Objekten verwendet werden können, da die Methode virtual getUID () nicht in der Lage ist, die Adresse der Variablen im Rahmen einer anderen Funktion zu übernehmen.

    
eyesathousand 23.09.2011 08:19
quelle

Tags und Links