QGlobalStatic Struct
template <typename Holder> struct QGlobalStaticDie Klasse „QGlobalStatic“ dient zur Implementierung eines globalen statischen Objekts. Mehr...
| Header: | #include <QGlobalStatic> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
Hinweis: Alle Funktionen in dieser Struktur sind threadsicher.
Öffentliche Typen
Öffentliche Funktionen
| bool | exists() const |
| bool | isDestroyed() const |
| operator QGlobalStatic<Holder>::Type *() | |
| QGlobalStatic<Holder>::Type & | operator*() |
| QGlobalStatic<Holder>::Type * | operator->() |
Makros
| Q_GLOBAL_STATIC(Type, variableName, ...) |
Ausführliche Beschreibung
QGlobalStatic<Holder> ist eine Template-Klasse, wobei Holder ein interner Typ ist, der durch das Makro Q_GLOBAL_STATIC() generiert wird. Der für den Benutzer sichtbare Typ des globalen statischen Objekts ist über den Typedef Type zugänglich.
Die Klasse `QGlobalStatic` ist die Frontend-API, die bei Verwendung von ` Q_GLOBAL_STATIC()` exportiert wird. Informationen zu den Anforderungen und zum Einsatzbereich des Makros finden Sie in der Dokumentation des Makros.
Normalerweise werden Sie diese Klasse nie direkt verwenden, sondern stattdessen das Makro ` Q_GLOBAL_STATIC()` wie folgt einsetzen:
Q_GLOBAL_STATIC(MyType, myGlobal)Das obige Beispiel erstellt ein Objekt vom Typ `QGlobalStatic` mit dem Namen ` myGlobal`. Nach der obigen Deklaration kann das Objekt ` myGlobal ` so verwendet werden, als wäre es ein Zeiger auf ein Objekt vom Typ ` MyType`, dessen Initialisierung garantiert genau einmal erfolgt. Zusätzlich zur Verwendung als Zeiger bietet das Objekt zwei Methoden zur Ermittlung des aktuellen Status der globalen Variable: ` exists()` und ` isDestroyed()`.
Siehe auch ` Q_GLOBAL_STATIC()`.
Dokumentation zu Mitgliedstypen
[alias] QGlobalStatic::Type
Dieser Typ entspricht dem Parameter „ Type “, der an die Makros „ Q_GLOBAL_STATIC()“ oder „Q_GLOBAL_STATIC_WITH_ARGS()“ übergeben wird. Er wird in den Rückgabetypen einiger Funktionen verwendet.
Dokumentation zu Mitgliedsfunktionen
[noexcept] bool QGlobalStatic::exists() const
Diese Funktion gibt „ true “ zurück, wenn das globale statische Objekt die Initialisierung bereits abgeschlossen hat (d. h., wenn der Konstruktor für den Typ bereits zurückgegeben hat) und die Destruktion noch nicht abgeschlossen ist. Beachten Sie insbesondere, dass diese Funktion „ false “ zurückgibt, wenn die Initialisierung noch im Gange ist.
Sobald diese Funktion einmal „true“ zurückgegeben hat, gibt sie bis zur Zerstörung des globalen statischen Objekts nie wieder „false“ zurück. Letzteres geschieht beim Beenden des Programms oder wenn das Plugin oder die Bibliothek, die das globale statische Objekt enthält, entladen wird.
Diese Funktion kann an jeder Stelle der Programmausführung sicher aufgerufen werden: Sie kann nicht fehlschlagen und verursacht keinen Deadlock. Außerdem bewirkt sie nicht, dass Inhalte erstellt werden, die noch nicht erstellt wurden.
Diese Funktion ist nützlich, wenn man die Anfangsbedingungen des globalen statischen Objekts bestimmen kann und einen möglicherweise aufwendigen Konstruktionsvorgang vermeiden möchte.
Im folgenden Codebeispiel wird diese Funktion beispielsweise verwendet, um die Erstellung des globalen statischen Objekts namens „ globalState “ zu umgehen und einen Standardwert zurückzugeben:
Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
if (globalState.exists())
return globalState->someState;
return QString();
}Hinweis zur Thread-Sicherheit: Diese Funktion ist insofern thread-sicher, als sie jederzeit von jedem Thread aus aufgerufen werden kann und stets eine gültige Antwort zurückgibt. Aufgrund der nicht-atomaren Natur der Erstellung kann diese Funktion jedoch für kurze Zeit nach Abschluss der Erstellung den Wert „false“ zurückgeben.
Hinweis zur Speicherreihenfolge: Diese Funktion gibt keine Garantien hinsichtlich der Speicherreihenfolge. Diese wird stattdessen durch die Zugriffsfunktionen gewährleistet, die den Zeiger oder die Referenz auf den Inhalt zurückgeben. Wenn Sie die Zugriffsfunktionen umgehen und versuchen, auf einen vom Konstruktor festgelegten globalen Zustand zuzugreifen, achten Sie darauf, die korrekte Semantik der Speicherreihenfolge zu verwenden, die von QAtomicInt oder QAtomicPointer bereitgestellt wird.
Siehe auch isDestroyed().
[noexcept] bool QGlobalStatic::isDestroyed() const
Diese Funktion gibt „ true “ zurück, wenn die Zerstörung des globalen statischen Objekts bereits abgeschlossen ist (d. h., wenn der Destruktor für den Typ bereits zurückgegeben hat). Beachten Sie insbesondere, dass diese Funktion „ false “ zurückgibt, wenn die Zerstörung noch im Gange ist.
Sobald diese Funktion einmal „true“ zurückgegeben hat, gibt sie nie wieder „false“ zurück, bis entweder das Programm neu gestartet wird oder das Plugin bzw. die Bibliothek, die das globale statische Objekt enthält, entladen und neu geladen wird.
Diese Funktion kann an jeder Stelle der Programmausführung sicher aufgerufen werden: Sie kann nicht fehlschlagen und verursacht kein Deadlock. Außerdem bewirkt sie nicht, dass Inhalte erstellt werden, die noch nicht erstellt wurden.
Diese Funktion ist in Code nützlich, der beim Beenden des Programms ausgeführt werden kann, um festzustellen, ob noch auf die Inhalte zugegriffen werden kann oder nicht.
Siehe auch ` exists()`.
QGlobalStatic::operator QGlobalStatic<Holder>::Type *()
Diese Funktion gibt die Adresse des Inhalts dieser globalen statischen Variablen zurück. Falls der Inhalt noch nicht angelegt wurde, wird er von dieser Funktion threadsicher angelegt. Falls der Inhalt bereits gelöscht wurde, gibt diese Funktion einen Nullzeiger zurück.
Diese Funktion kann beispielsweise verwendet werden, um den Zeiger auf den Inhalt der globalen statischen Variablen in einer lokalen Variablen zu speichern und so mehrere Aufrufe der Funktion zu vermeiden. Die Implementierung von ` Q_GLOBAL_STATIC()` ist bereits recht effizient, aber in leistungskritischen Abschnitten kann es sinnvoll sein, dem Compiler ein wenig unter die Arme zu greifen. Zum Beispiel:
Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
if (globalState::isDestroyed())
return QString();
MyType *state = globalState;
if (state->condition)
return state->value;
else
return state->worth;
}Siehe auch ` operator->()` und ` operator*()`.
QGlobalStatic<Holder>::Type &QGlobalStatic::operator*()
Diese Funktion gibt eine Referenz auf den Inhalt dieser globalen statischen Variablen zurück. Falls der Inhalt noch nicht angelegt wurde, wird er von dieser Funktion threadsicher angelegt.
Diese Funktion prüft nicht, ob der Inhalt bereits zerstört wurde. Wird diese Funktion aufgerufen, nachdem das Objekt zerstört wurde, gibt sie eine ungültige Referenz zurück, die nicht verwendet werden darf.
Siehe auch exists() und isDestroyed().
QGlobalStatic<Holder>::Type *QGlobalStatic::operator->()
Diese Funktion gibt die Adresse des Inhalts dieser globalen statischen Variablen zurück. Falls der Inhalt noch nicht angelegt wurde, wird er von dieser Funktion threadsicher angelegt.
Diese Funktion prüft nicht, ob der Inhalt bereits zerstört wurde, und gibt niemals null zurück. Wird diese Funktion aufgerufen, nachdem das Objekt zerstört wurde, gibt sie einen „dangling pointer“ zurück, der nicht dereferenziert werden sollte.
Siehe auch exists() und isDestroyed().
Makro-Dokumentation
Q_GLOBAL_STATIC(Type, variableName, ...)
Erstellt ein globales und statisches Objekt vom Typ „ QGlobalStatic “ mit dem Namen „ variableName “. Es verhält sich wie ein Zeiger auf „ Type “. Das von Q_GLOBAL_STATIC erstellte Objekt initialisiert sich bei der ersten Verwendung selbst, was bedeutet, dass es die Ladezeit der Anwendung oder der Bibliothek nicht erhöht. Zudem wird das Objekt auf allen Plattformen threadsicher initialisiert.
Seit Qt 6.3 akzeptiert dieses Makro variadische Argumente, die zur Initialisierung des Objekts verwendet werden, wodurch die Verwendung von ` Q_GLOBAL_STATIC_WITH_ARGS ` überflüssig wird. Bitte beachten Sie, dass die Argumente im Gegensatz zum älteren Makro keine zusätzlichen Klammern erfordern.
Die typische Verwendung dieses Makros sieht wie folgt aus, und zwar in einem globalen Kontext (d. h. nicht innerhalb einer Funktion oder eines Klassenkörpers):
Q_GLOBAL_STATIC(MyType, myGlobal)Dieses Makro soll globale statische Objekte ersetzen, die kein POD (Plain Old Data, oder in C++11-Begriffen: nicht aus einem trivialen Typ bestehend) sind – daher der Name. Der folgende C++-Code erstellt beispielsweise ein globales statisches Objekt:
static MyType myGlobal;Im Vergleich zu `Q_GLOBAL_STATIC` und unter der Annahme, dass ` MyType ` eine Klasse oder Struktur ist, die über einen Konstruktor, einen Destruktor oder anderweitig nicht POD ist, weist Letzteres folgende Nachteile auf:
- Es erfordert eine Initialisierung von „
myGlobal“ zur Ladezeit (das heißt, der Standardkonstruktor für „MyType“ wird beim Laden der Bibliothek oder der Anwendung aufgerufen); - Das Objekt wird auch dann initialisiert, wenn es nie verwendet wird;
- die Reihenfolge der Initialisierung und Zerstörung zwischen verschiedenen Übersetzungseinheiten ist nicht festgelegt, was dazu führen kann, dass die Konstruktoren oder Destruktoren anderer globaler Variablen diese vor der Initialisierung oder nach der Zerstörung verwenden.
Das Makro `Q_GLOBAL_STATIC` löst all diese Probleme, indem es eine threadsichere Initialisierung bei der ersten Verwendung garantiert und es dem Benutzer ermöglicht, abzufragen, ob der Typ bereits zerstört wurde, um das Problem der Nutzung nach der Zerstörung zu vermeiden (siehe ` QGlobalStatic::isDestroyed()`).
Konstruktor und Destruktor
Wenn für `Q_GLOBAL_STATIC` lediglich ein Typ und ein Variablenname angegeben werden, muss dessen ` Type ` öffentlich standardkonstruierbar und öffentlich destruktierbar sein. Andernfalls muss „ Type “ über einen öffentlichen Konstruktor verfügen, der die übrigen Argumente des Makros akzeptiert. Bei „Q_GLOBAL_STATIC_WITH_ARGS()“ muss ein öffentlicher Konstruktor vorhanden sein, der das dritte Argument des Makros als Parameterliste akzeptiert.
Es ist nicht möglich, `Q_GLOBAL_STATIC` mit einem ` Type ` zu verwenden, dessen relevanter Konstruktor oder Destruktor als `protected` oder `private` deklariert ist. Wenn der betreffende Typ diese Mitglieder als „protected“ deklariert, lässt sich das Problem umgehen, indem man von diesem Typ ableitet und einen öffentlichen Konstruktor sowie Destruktor erstellt. Wenn der Typ sie als „private“ deklariert, ist vor der Ableitung eine „friend“-Deklaration erforderlich.
Beispielsweise reicht Folgendes aus, um ` MyType ` basierend auf einem zuvor definierten ` MyOtherType ` zu erstellen, der einen geschützten Standardkonstruktor und/oder einen geschützten Destruktor besitzt (oder diese als privat deklariert, aber auch ` MyType ` als „friend“ deklariert).
class MyType : public MyOtherType { };
Q_GLOBAL_STATIC(MyType, myGlobal)Ein Konstruktorkörper für ` MyType ` ist nicht erforderlich, da der Destruktor ein implizites Mitglied ist – ebenso wie der Standardkonstruktor, sofern keine anderen Konstruktoren definiert sind. Für die Verwendung mit Argumenten nach ` Type ` und ` variableName` oder mit `Q_GLOBAL_STATIC_WITH_ARGS()` ist jedoch ein geeigneter Konstruktorkörper erforderlich:
class MyType : public MyOtherType
{
public:
MyType(int i) : MyOtherType(i) {}
};
Q_GLOBAL_STATIC(MyType, myGlobal, 42)Alternativ (da C++11 ererbbare Konstruktoren eingeführt hat) könnte man schreiben:
class MyType : public MyOtherType
{
public:
using MyOtherType::MyOtherType;
};
Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))Platzierung
Das Makro `Q_GLOBAL_STATIC` erstellt einen Typ und eine Variable dieses Typs, die zwangsläufig statisch ist, im globalen Geltungsbereich. Es ist nicht möglich, das Makro `Q_GLOBAL_STATIC` innerhalb einer Funktion oder im Körper einer Klasse zu platzieren (dies führt zu Kompilierungsfehlern).
Noch wichtiger ist, dass dieses Makro in Quelldateien platziert werden sollte, niemals in Header-Dateien. Da das resultierende Objekt eine statische Verknüpfung aufweist, wird das Objekt – wenn das Makro in einer Header-Datei platziert und von mehreren Quelldateien eingebunden wird – mehrfach definiert, was jedoch keine Linkerfehler verursacht. Stattdessen verweist jede Übersetzungseinheit auf ein anderes Objekt, was zu subtilen und schwer aufzuspürenden Fehlern führen kann.
Nicht empfohlene Verwendungszwecke
Beachten Sie, dass die Verwendung des Makros bei Typen, die POD sind oder über C++11-constexpr-Konstruktoren verfügen (trivial konstruierbar und destruktierbar), nicht empfohlen wird. Für diese Typen wird weiterhin die Verwendung von regulärem „static“ empfohlen, sei es global oder funktionslokal.
Dieses Makro funktioniert zwar, verursacht jedoch unnötigen Overhead.
Reentranz, Thread-Sicherheit, Deadlocks und Ausnahmensicherheit bei der Konstruktion
Das Makro `Q_GLOBAL_STATIC` erstellt ein Objekt, das sich bei der ersten Verwendung auf threadsichere Weise selbst initialisiert: Wenn mehrere Threads gleichzeitig versuchen, das Objekt zu initialisieren, führt nur ein Thread die Initialisierung durch, während alle anderen Threads auf den Abschluss warten.
Wenn der Initialisierungsprozess eine Ausnahme auslöst, gilt die Initialisierung als nicht abgeschlossen und wird erneut versucht, sobald die Steuerung eine beliebige Nutzung des Objekts erreicht. Falls Threads auf die Initialisierung warten, wird einer von ihnen geweckt, um die Initialisierung zu versuchen.
Das Makro gibt keine Garantie hinsichtlich der Reentranz aus demselben Thread. Wenn von innerhalb des eigenen Konstruktors direkt oder indirekt auf das globale statische Objekt zugegriffen wird, kommt es mit Sicherheit zu einem Deadlock.
Zudem kann es zu einem Deadlock kommen, wenn zwei Q_GLOBAL_STATIC-Objekte in zwei verschiedenen Threads initialisiert werden und die Initialisierungssequenz des einen auf das andere zugreift. Aus diesem Grund wird empfohlen, globale statische Konstruktoren einfach zu halten oder, falls dies nicht möglich ist, sicherzustellen, dass während der Konstruktion keine gegenseitigen Abhängigkeiten bei der Verwendung globaler statischer Objekte bestehen.
Zerstörung
Wird das Objekt während der Laufzeit des Programms nie verwendet – abgesehen von den Funktionen ` QGlobalStatic::exists()` und ` QGlobalStatic::isDestroyed()` –, wird der Inhalt vom Typ ` Type ` nicht erstellt und es findet keine Operation beim Programmausstieg statt.
Wird das Objekt erstellt, wird es beim Programmausstieg zerstört, ähnlich wie bei der C-Funktion ` atexit() `. Auf den meisten Systemen wird der Destruktor sogar aufgerufen, wenn die Bibliothek oder das Plugin vor dem Programmausstieg aus dem Speicher entladen wird.
Da die Zerstörung beim Programmausstieg erfolgen soll, wird keine Thread-Sicherheit gewährleistet. Dies gilt auch für den Fall, dass das Plugin oder die Bibliothek entladen wird. Da Destruktoren zudem keine Ausnahmen auslösen sollen, wird auch keine Ausnahmensicherheit gewährleistet.
Reentranz ist jedoch zulässig: Während der Destruktion ist es möglich, auf das globale statische Objekt zuzugreifen, und der zurückgegebene Zeiger entspricht dem Zustand vor Beginn der Destruktion. Nach Abschluss der Destruktion ist der Zugriff auf das globale statische Objekt nicht mehr zulässig, außer wie in der QGlobalStatic -API angegeben.
Siehe auch ` Q_APPLICATION_STATIC()` und ` QGlobalStatic`.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.