Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Inicjator globalny wywołuje funkcję inną niż constexpr "symbol" (i.22)
podstawowe wytyczne dotyczące języka C++
I.22: Unikaj złożonego inicjowania obiektów globalnych
Kolejność wykonywania inicjatorów dla obiektów globalnych może być niespójna lub niezdefiniowana, co może prowadzić do problemów, które są trudne do odtworzenia i zbadania. Aby uniknąć takich problemów, globalne inicjatory nie powinny zależeć od kodu zewnętrznego, który jest wykonywany w czasie wykonywania, i może to zależeć od danych, które nie są jeszcze zainicjowane. Ta reguła flaguje przypadki, w których obiekty globalne wywołają funkcje w celu uzyskania ich wartości początkowych.
Uwagi
Reguła ignoruje wywołania
constexprfunkcji lub funkcji wewnętrznych przy założeniu, że te wywołania będą obliczane w czasie kompilacji lub gwarantują przewidywalne wykonanie w czasie wykonywania.Wywołania funkcji wbudowanych są nadal oflagowane, ponieważ kontroler nie próbuje analizować ich implementacji.
Ta reguła może być hałaśliwa w wielu typowych scenariuszach, w których zmienna typu zdefiniowanego przez użytkownika (lub standardowego kontenera) jest inicjowana globalnie. Często jest to spowodowane wywołaniami konstruktorów i destruktorów. Nadal jest to prawidłowe ostrzeżenie, ponieważ wskazuje na to, gdzie może istnieć nieprzewidywalne zachowanie lub gdzie przyszłe zmiany kodu zewnętrznego mogą powodować niestabilność.
Statyczne składowe klasy są uznawane za globalne, więc ich inicjatory są również sprawdzane.
Nazwa analizy kodu: NO_GLOBAL_INIT_CALLS
Przykłady
Sprawdzanie wersji zewnętrznej:
// 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
Sprawdzanie wersji zewnętrznej sprawiło, że stał się bardziej niezawodny:
// 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;
}