警告 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;
}