Share via


警告 C26426

グローバル初期化子は、constexpr 以外の関数 'symbol' を呼び出します (i.22)

C++ Core Guidelines

I.22: グローバル オブジェクトの複雑な初期化を回避する

グローバル オブジェクトに対する初期化子の実行順序が一貫性がない、または未定義である可能性があるため、再現や調査が困難な問題が発生する可能性があります。 このような問題を回避するために、グローバル初期化子は、実行時に実行される外部コードに依存しないようにし、まだ初期化されていないデータに依存する可能性があります。 この規則は、グローバル オブジェクトが関数を呼び出して初期値を取得するケースに対してフラグを設定します。

解説

  • ルールは、これらの呼び出しがコンパイル時に constexpr 計算されるか、実行時に予測可能な実行が保証されることを前提として、関数または組み込み関数の呼び出しを無視します。

  • インライン関数の呼び出しは、チェックer が実装の分析を試みないため、フラグが引き続き設定されます。

  • このルールは、ユーザー定義型 (または標準コンテナー) の変数がグローバルに初期化される多くの一般的なシナリオで、ノイズが発生する可能性があります。 多くの場合、コンストラクターとデストラクターの呼び出しが原因です。 これは、予期しない動作が存在する可能性がある場所、または外部コードの将来の変更によって不安定になる可能性がある場所を指しているため、依然として有効な警告です。

  • 静的クラス メンバーはグローバルと見なされるため、初期化子も検査されます。

コード分析名: NO_GLOBAL_INIT_CALLS

外部バージョンのチェック:

// api.cpp
int api_version = API_DEFAULT_VERSION; // Assume it can change at run time, hence non-const.
int get_api_version() noexcept {
    return api_version;
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode = get_api_version() <= API_LEGACY_VERSION; // C26426, also stale value

外部バージョンチェック信頼性が向上しました。

// api.cpp
int& api_version() noexcept {
    static auto value = API_DEFAULT_VERSION;
    return value;
}
int get_api_version() noexcept {
    return api_version();
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode() noexcept {
    return get_api_version() <= API_LEGACY_VERSION;
}