QGlobalStatic Struct
template <typename Holder> struct QGlobalStaticQGlobalStatic クラスは、グローバル静的オブジェクトを実装するために使用します。詳細...
Header: | #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, staticType)
上記の例では、staticType
という QGlobalStatic 型のオブジェクトを作成しています。上記の例では、staticType
という 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 *()
この関数は、このグローバル・スタティックのコンテンツのアドレスを返します。コンテンツがまだ作成されていない場合、この関数によってスレッドセーフに作成されます。コンテンツが既に破棄されている場合、この関数はヌル・ポインタを返します。
この関数は、例えば、グローバルスタティックの内容へのポインタをローカル変数に格納するために使用することができます。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, staticType)
このマクロは、POD(Plain Old Data、C++11 の用語では、些細な型でできていない)でないグローバルな静的オブジェクトを置き換えることを目的としています。たとえば、次の C++ コードはグローバル静的オブジェクトを作成します:
static MyType staticType;
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としている場合は、派生する前にフレンド宣言が必要である。
例えば、protected default コンストラクタやprotectedデストラクタを持つ(あるいはprivateとして持つが、MyType
をフレンドとして定義する)以前に定義されたMyOtherType
に基づいてMyType
を作成するには、以下のようにすれば十分である。
class MyType : public MyOtherType { }; Q_GLOBAL_STATIC(MyType, staticType)
デストラクタは暗黙のメンバであり、他のコンストラクタが定義されていない場合はデフォルトのコンストラクタも暗黙のメンバであるため、MyType
のボディは必要ありません。しかし、Q_GLOBAL_STATIC_WITH_ARGS() で使用する場合は、適切なコンストラクタ本体が必要です:
class MyType : public MyOtherType { public: MyType(int i) : MyOtherType(i) {} }; Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42))
また、コンパイラが C++11 の継承コンストラクタをサポートしている場合は、次のように記述することもできます:
class MyType : public MyOtherType { public: using MyOtherType::MyOtherType; }; Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (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も参照のこと 。
本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。