C++ 静的初期化の順序

最終更新: 2023-12-26 14:30:46 +0800 +0800
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

C++ では、記憶域期間とスコープが独立して決まります。静的記憶域およびスレッド記憶域に対する初期化と破棄の規則によって、オブジェクトを main より前に利用できるか、初回使用時に利用できるか、またはスレッドごとに一度だけ利用できるかが決まります。

記憶域期間と初期化フェーズ #

名前空間スコープのオブジェクト、静的データメンバー、およびブロックスコープの static オブジェクトには静的記憶域期間があります。thread_local オブジェクトにはスレッド記憶域期間があります。各スレッドは個別のインスタンスを持ち、そのインスタンスは宣言および実装の規則に従って、そのスレッドの開始時または初回使用時に初期化されます。

静的記憶域またはスレッド記憶域を持つ変数が条件を満たす場合、定数初期化が行われます。それ以外の場合、その変数はゼロ初期化されます。定数初期化とゼロ初期化を合わせて静的初期化と呼び、静的初期化は動的初期化より前に完了します。したがって、constinit 変数は定数初期化されなければならず、constexpr オブジェクトは初期化要件を明示する有用な方法です。

cpp
constinit int process_limit = 256;
constexpr int cache_line_bytes = 64;

constinit はオブジェクトを不変にはしません。動的初期化を必要とする初期化子を拒否するだけです。

順序付けの境界 #

1つの翻訳単位にある通常の非インライン名前空間スコープ変数の動的初期化は、定義順序によって順序付けられます。翻訳単位をまたぐ動的初期化には、信頼できるソースコード上の順序はありません。順不同に順序付けられる場合や、遅延初期化の規則による影響を受ける場合があります。そのため、別の非ローカルオブジェクトを読み取る非ローカル初期化子は、そのオブジェクトが意図ますが、デストラクターが別のアクセサーを呼び出す場合には、同様の危険が発生する可能性があります。

終了処理で相互作用するリソースについては、明示的な所有権とシャットダウン順序を優先してください。プロセスの存続期間全体にわたるサービスでは、オペレーティングシステムによる回収を選択した契約として、意図的に破棄しない場合があります。その選択を文書化し、偶然の破棄順序に依存しないでください。

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)