Инициализация статических полей класса. Ч3
В первой части мы разобрали порядок инициализации статических поле в случае их out-of-class определения. Однако в современных плюсах редко, кто вне описания класса инициализирует статические поля. Все потому что в С++17 появились инлайн переменные, которые позволяют не нарушать ODR при наличии их определения в разных единицах трансляции. Подробнее об этом тут. Эта фича позволила определять статические поля сразу внутри описания класса. Более подробно об этом тут.
Ну и встает вопрос: в каком порядке инициализируются inline static class members?
В целом, ответ такой же: в порядке определения. Только эти определения теперь совмещены с объявлением, поэтому можно сказать, что инициализация происходит в порядке появления этих полей в описании класса. Спасибо Артему Кузнецову, что указал в комментариях на эту особенность)
Ну и для того, чтобы пост был не таким скучным, давайте попробуем смешать обычные статические мемберы и инлайновые и посмотрим, как эта смесь будет себя вести.
Выглядит это примерно так:
Вывод будет таким:
В целом, картина довольно понятная. Если линкер ставит инициализацию статиков по порядку их определения, то здесь прослеживается та же история. Первыми инициализируются инлайны по порядку появления их в классе, а последним инициализируется неинлайновое поле, даже с учетом того, что оно объявлено между двумя первыми.
Так что порядок следования определений - наше все.
Rely on explicitly stated rules. Stay cool.
#cpp17 #cppcore
В первой части мы разобрали порядок инициализации статических поле в случае их out-of-class определения. Однако в современных плюсах редко, кто вне описания класса инициализирует статические поля. Все потому что в С++17 появились инлайн переменные, которые позволяют не нарушать ODR при наличии их определения в разных единицах трансляции. Подробнее об этом тут. Эта фича позволила определять статические поля сразу внутри описания класса. Более подробно об этом тут.
Ну и встает вопрос: в каком порядке инициализируются inline static class members?
В целом, ответ такой же: в порядке определения. Только эти определения теперь совмещены с объявлением, поэтому можно сказать, что инициализация происходит в порядке появления этих полей в описании класса. Спасибо Артему Кузнецову, что указал в комментариях на эту особенность)
Ну и для того, чтобы пост был не таким скучным, давайте попробуем смешать обычные статические мемберы и инлайновые и посмотрим, как эта смесь будет себя вести.
Выглядит это примерно так:
struct Helper {
Helper(int num) : data{num} {
std::cout << "Helper " << num << std::endl;
}
private:
int data;
};
struct Class {
static inline Helper a{1};
static Helper b;
static inline Helper c{2};
};
Helper Class::b{3};
int main() {}
Вывод будет таким:
Helper 1
Helper 2
Helper 3
В целом, картина довольно понятная. Если линкер ставит инициализацию статиков по порядку их определения, то здесь прослеживается та же история. Первыми инициализируются инлайны по порядку появления их в классе, а последним инициализируется неинлайновое поле, даже с учетом того, что оно объявлено между двумя первыми.
Так что порядок следования определений - наше все.
Rely on explicitly stated rules. Stay cool.
#cpp17 #cppcore