分享方式:


警告 C26426

全域初始化運算式會呼叫非 constexpr 函式 ' symbol ' (i.22)

C++ Core Guidelines

I.22 :避免全域物件的複雜初始化

全域物件的初始化運算式執行順序可能不一致或未定義,這可能會導致難以重現和調查的問題。 為了避免這類問題,全域初始化運算式不應該相依于在執行時間執行的外部程式碼,而且可能相依于尚未初始化的資料。 此規則會標幟全域物件呼叫函式以取得其初始值的情況。

備註

  • 此規則會忽略函式或內建函式的 constexpr 呼叫,假設這些呼叫是在編譯時期計算,或保證執行時間可預測的執行。

  • 內嵌函式的呼叫仍會標示為旗標,因為檢查程式不會嘗試分析其實作。

  • 在許多常見的案例中,此規則可能會很吵鬧,其中使用者定義型別的變數(或標準容器)會全域初始化。 這通常是因為呼叫建構函式和解構函式。 它仍然是有效的警告,因為它指向可能存在無法預期行為的位置,或外部程式碼的未來變更可能會造成不穩定的地方。

  • 靜態類別成員會視為全域,因此也會檢查其初始化運算式。

程式碼分析名稱: 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;
}