QGlobalStatic Struct

template <typename Holder> struct QGlobalStatic

QGlobalStatic クラスは、グローバル静的オブジェクトを実装するために使用します。詳細...

ヘッダー #include <QGlobalStatic>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core

注意:この構造体の関数はすべてスレッドセーフです。

パブリック型

パブリック関数

bool exists() const
bool isDestroyed() const
QGlobalStatic<Holder>::Type *operator QGlobalStatic<Holder>::Type *()
QGlobalStatic<Holder>::Type &operator*()
QGlobalStatic<Holder>::Type *operator->()

マクロ

Q_GLOBAL_STATIC(Type, VariableName, ...)

詳細説明

QGlobalStatic クラスは、Q_GLOBAL_STATIC() が使用されたときにエクスポートされるフロントエンド API です。このクラスを使用するタイミングや要件については、マクロのドキュメントを参照してください。

通常、このクラスを直接使用することはなく、次のようにQ_GLOBAL_STATIC() または Q_GLOBAL_STATIC_WITH_ARGS() マクロを使用します:

Q_GLOBAL_STATIC(MyType, myGlobal)

上記の例では、myGlobal という QGlobalStatic 型のオブジェクトを作成しています。上記の例では、myGlobal という QGlobalStatic 型のオブジェクトが作成されています。上記の宣言後、 オブジェクトは、ポインタのように使用することができます。ポインタとして使用するだけでなく、このオブジェクトには、グローバルの現在のステータスを判断するための2つのメソッドが用意されています:exists() とisDestroyed()。

Q_GLOBAL_STATIC() およびQ_GLOBAL_STATIC_WITH_ARGS()も参照

メンバ型ドキュメント

[alias] QGlobalStatic::Type

この型は、Q_GLOBAL_STATIC()またはQ_GLOBAL_STATIC_WITH_ARGS()マクロに渡されるType パラメータに相当する。いくつかの関数の戻り値型に使用されます。

メンバ関数のドキュメント

[noexcept] bool QGlobalStatic::exists() const

この関数は、グローバル静的オブジェクトがすでに初期化を完了し(つまり、その型のコンストラクタがすでに返され)、まだ破棄を完了していない場合、true を返します。特に、初期化がまだ進行中の場合、この関数はfalse を返すことに注意してください。

この関数は一度trueを返すと、グローバル静的オブジェクトが破棄されるまで二度とfalseを返しません。後者は、プログラムの終了時か、グローバル・スタティックを含むプラグインやライブラリがアンロードされたときに起こります。

この関数は、プログラム実行のどの時点でも安全に呼び出すことができます。さらに、コンテンツがまだ作成されていない場合は作成されません。

この関数は、グローバル静的オブジェクトの初期条件を決定でき、高価な構築操作を避けたい場合に便利です。

例えば、以下のコード・サンプルでは、この関数を使用してglobalState というグローバル・スタティックの作成をショートカットし、デフォルト値を返しています:

Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
    if (globalState.exists())
        return globalState->someState;
    return QString();
}

スレッドセーフに関する注意:この関数は、どのスレッドからでもいつでも呼び出すことができ、常に有効な応答を返すという意味でスレッドセーフです。しかし、コンストラクションの非アトミックな性質により、この関数はコンストラクション完了後しばらくは偽を返すことがある。

メモリ順序に関する注意:この関数はメモリ順序を保証しません。その代わりに、内容へのポインタや参照を返すアクセサ関数が提供します。アクセッサ関数をバイパスしてコンストラクタが設定したグローバル状態にアクセスしようとする場合は、QAtomicInt またはQAtomicPointer が提供する正しいメモリ順序セマンティクスを使用するようにしてください。

isDestroyed()も参照のこと

[noexcept] bool QGlobalStatic::isDestroyed() const

この関数は、グローバル静的オブジェクトがすでに破壊を完了した場合(つまり、その型のデストラクタがすでに戻ってきた場合)、true を返します。具体的には、破壊がまだ進行中の場合、この関数はfalse を返すことに注意してください。

この関数が一度trueを返すと、プログラムが再起動されるか、グローバル静的オブジェクトを含むプラグインやライブラリがアンロードされて再ロードされるまで、二度とfalseを返すことはありません。

この関数は、プログラム実行のどの時点でも安全に呼び出すことができます。さらに、コンテンツがまだ作成されていない場合は、作成されません。

この関数は、プログラムのシャットダウン時に実行される可能性のあるコードで、コンテンツにまだアクセスできるかどうかを判断するのに便利です。

exists()も参照のこと

QGlobalStatic<Holder>::Type *QGlobalStatic::operator QGlobalStatic<Holder>::Type *()

この関数は、このグローバル・スタティックのコンテンツのアドレスを返します。コンテンツがまだ作成されていない場合は、この関数によってスレッドセーフに作成されます。コンテンツが既に破棄されている場合、この関数は NULL ポインタを返します。

この関数は、例えば、グローバル・スタティックの内容へのポインタをローカル変数に格納するために使用することができます。Q_GLOBAL_STATIC() の実装はすでにかなり効率的ですが、パフォーマンスが重要な部分では、コンパイラを少し助けてあげると便利かもしれません。例えば

Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
    MyType *state = globalState;
    if (!state) {
        // we're in a post-destruction state
        return QString();
    }
    if (state->condition)
        return state->value1;
    else
        return state->value2;
}

operator->() およびoperator*()参照のこと。

QGlobalStatic<Holder>::Type &QGlobalStatic::operator*()

この関数は、このグローバル・スタティックの内容への参照を返します。コンテンツがまだ作成されていない場合、この関数によってスレッドセーフに作成されます。

この関数は、コンテンツが既に破棄されているかどうかはチェックしません。オブジェクトが破棄された後にこの関数を呼び出すと、無効な参照が返されます。

QGlobalStatic<Holder>::Type *QGlobalStatic::operator->()

この関数は、このグローバル・スタティックのコンテンツのアドレスを返します。コンテンツがまだ作成されていない場合は、この関数によってスレッドセーフに作成されます。

この関数は、コンテンツが既に破棄されているかどうかをチェックせず、NULL を返すことはありません。オブジェクトが破棄された後にこの関数が呼び出された場合、再参照してはならないダングリングポインタが返されます。

マクロ・ドキュメント

Q_GLOBAL_STATIC(Type, VariableName, ...)

QGlobalStatic VariableName TypeQ_GLOBAL_STATIC によって作成されたオブジェクトは、最初の使用時にそれ自身を初期化するため、アプリケーションやライブラリのロード時間が長くなることはありません。さらに、オブジェクトはすべてのプラットフォームでスレッドセーフな方法で初期化されます。

Qt 6.3以降、このマクロはオブジェクトを初期化するために使用される可変引数を認め、Q_GLOBAL_STATIC_WITH_ARGS 。旧来のマクロと異なり、引数に括弧を追加する必要がないことに注意してください。

このマクロの典型的な使い方は、グローバルなコンテキスト(つまり、関数本体の外)での次のようなものである:

Q_GLOBAL_STATIC(MyType, myGlobal)

このマクロは、POD(Plain Old Data、C++11 の用語では些細な型でできていない)でないグローバルな静的オブジェクトを置き換えることを目的としており、これが名前の由来です。たとえば、次の C++ コードはグローバル静的オブジェクトを作成します:

static MyType myGlobal;

Q_GLOBAL_STATIC と比較して、また、MyType がコンストラクタやデストラクタを持つクラスまたは構造体である場合、またはその他の非 POD 型である場合、上記の方法には次のような欠点があります:

  • MyType をロード時に初期化する必要がある(つまり、ライブラリやアプリケーションのロード時にMyType のデフォルトコンストラクタが呼び出される);
  • 一度も使用されなくても型が初期化される;
  • 異なる翻訳単位間での初期化と破棄の順序が決定されないため、初期化前または破棄後に使用される可能性があります;

Q_GLOBAL_STATICマクロは、最初の使用時にスレッドセーフな初期化を保証し、型がすでに破棄されたかどうかを問い合わせることができるようにすることで、上記の問題をすべて解決し、破棄後の使用問題を回避します(QGlobalStatic::isDestroyed()を参照)。

コンストラクタとデストラクタ

Q_GLOBAL_STATIC の場合、Type 型は、公開されたデフォルトでコンストラクタ可能で、公開されたデストラクタ可能でなければなりません。Q_GLOBAL_STATIC_WITH_ARGS() では、渡された引数に一致するパブリック・コンストラクタが必要です。

Q_GLOBAL_STATIC_WITH_ARGS() では、引数にマッチする protected または private コンストラクタが必要です。問題の型がそれらのメンバを protected にしている場合は、その型から派生して public のコンストラクタとデストラクタを作成することで、問題を解決することができます。もしその型がそれらのメンバをprivateとしている場合は、派生する前にフレンド宣言が必要である。

たとえば、MyType を、protected default コンストラクタやprotected デストラクタを持つ(あるいはprivateとして持つが、MyType をフレンドとして定義している)、以前に定義されたMyOtherType に基づいて作成するには、以下のようにすればよい。

class MyType : public MyOtherType { };
Q_GLOBAL_STATIC(MyType, myGlobal)

デストラクタは暗黙のメンバであり、他のコンストラクタが定義されていない場合はデフォルトのコンストラクタも暗黙のメンバであるため、MyType のボディは必要ありません。しかし、Q_GLOBAL_STATIC_WITH_ARGS() で使用する場合は、適切なコンストラクタ本体が必要です:

class MyType : public MyOtherType
{
public:
    MyType(int i) : MyOtherType(i) {}
};
Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))

また、コンパイラが C++11 の継承コンストラクタをサポートしている場合は、次のように記述することもできます:

class MyType : public MyOtherType
{
public:
    using MyOtherType::MyOtherType;
};
Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))

配置

Q_GLOBAL_STATIC マクロは、グローバル・スコープで必然的に静的な型を作成します。Q_GLOBAL_STATIC マクロを関数内に配置することはできません(配置するとコンパイル エラーが発生します)。

さらに重要なことは、このマクロはソース・ファイルに置くべきで、決してヘッダーに置くべきではありません。このマクロがヘッダーに置かれ、複数のソース・ファイルにインクルードされると、オブジェクトは複数回定義されることになり、リンク・エラーは発生しません。その代わり、各翻訳ユニットは異なるオブジェクトを参照することになり、微妙で追跡しにくいエラーが発生する可能性があります。

このマクロは、POD 型または C++11 constexpr コンストラクタ(些細な構成可能および破壊可能)を持つ型での使用は推奨されないことに注意してください。これらの型では、グローバルまたは関数ローカルの通常の static を使用することをお勧めします。

このマクロは動作しますが、不要なオーバーヘッドが追加されます。

再トランシー、スレッド安全性、デッドロック、構築時の例外安全性

Q_GLOBAL_STATIC マクロは、最初の使用時にスレッドセーフな方法で自身を初期化するオブジェクトを作成します。複数のスレッドが同時にオブジェクトを初期化しようとすると、1 つのスレッドだけが初期化を続行し、他のすべてのスレッドは完了を待ちます。

初期化処理で例外がスローされた場合、初期化は完了していないとみなされ、制御がオブジェクトの使用に達した時点で再度初期化が試みられる。初期化を待っているスレッドがあれば、そのうちの1つが初期化を試みるために起こされる。

マクロは、同じスレッドからの再連続性については保証しない。グローバル静的オブジェクトにコンストラクタ内から直接または間接的にアクセスすると、必ずデッドロックが発生する。

また、2 つの Q_GLOBAL_STATIC オブジェクトが 2 つのスレッドで初期化され、それぞれの初期化シーケンスでもう一方のオブジェクトにアクセスすると、デッドロックが発生する可能性があります。そのため、グローバルスタティックのコンストラクタはシンプルに保つことを推奨します。

破壊

QGlobalStatic::exists() とQGlobalStatic::isDestroyed() 関数は別として、プログラムの存続期間中にオブジェクトが一度も使用されなかった場合、Type 型のコンテンツは作成されず、終了時の操作も行われません。

オブジェクトが作成された場合、Cのatexit 関数と同様に、終了時に破棄されます。実際、ほとんどのシステムでは、終了前にライブラリやプラグインがメモリからアンロードされると、デストラクタも呼び出されます。

デストラクタはプログラムの終了時に実行されるため、スレッドセーフは提供されません。これには、プラグインやライブラリーがアンロードされた場合も含まれます。さらに、デストラクタは例外をスローしないことになっているので、例外安全性も提供されない。

ただし、再入可能性はあります。破棄中は、グローバル静的オブジェクトにアクセスすることが可能で、返されるポインターは破棄開始前と同じです。破壊が完了した後は、QGlobalStatic APIに記載されている場合を除き、グローバル静的オブジェクトへのアクセスは許可されません。

Q_GLOBAL_STATIC_WITH_ARGS()、Q_APPLICATION_STATIC()、QGlobalStaticも参照のこと

© 2025 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.