Разница между inline и static переменной

155
14 ноября 2019, 19:20

В 17 стандарте есть новая фича: inline переменные. Но я не совсем понимаю, а в чем разница между inline и static переменной?

Answer 1

До С++17 было два основных способа объявить/определить глобальную переменную, которая используется в нескольких единицах трансляции:

//my.h
extern int foo;
static int bar = 0;
//my.cpp
int foo = 0;
  • Переменная foo — обычная переменная со внешним связыванием, объявлена в хедере и обределена/инициализирутся точно в одной единице трансляции.

  • Переменная bar — статическая переменная, объявлена и инициализируется в хедере. При этом каждая единица трансляции работает со своей копией объекта. Зачастую это ошибка.

В c++17 достаточно сделать:

//my.h
inline int baz = 0;

По большей части это просто синтаксический сахар: baz, объявлена и инициализируется в хедере, как и в случае static, но все единицы трансляции работают с одним и тем же объектом, как в случае с extern, а компилятор сам выберет модуль, куда пристроит символ (по аналогии с inline-функциями).​ Оптимизационного потенциала это несёт крайне мало т.к. почти все его перспективные применения уже покрыты constexpr​.

Answer 2

Не-const переменная, объявленная на уровне пространства имен без слова static имеет внешнее связывание, т.е. существует в единственном экземпляре во всей программе.

Переменная, объявленная на уровне пространства имен со словом static имеет внутреннее связывание, т.е. существует как отдельная переменная в каждой единице трансляции, в которой объявлена.

Так было всегда.

inline никак не меняет этих свойств. inline лишь позволяет нам делать множественные определения переменных с внешним связыванием в разных единицах трансляции, не вызывая при этом нарушения ODR (полностью аналогично тому, как inline влияет на функции). Без inline нам придется идти по традиционному пути: помещать в заголовочные файлы extern-объявления глобальных переменных, а определения с инициализаторами прятать в файлах реализации. Это более громоздко и это приводит к тому, что инициализатор глобальной переменной виден лишь в одной единице трансляции. С inline все сводится к одному-единственному объявлению-определению, которое можно делать в заголовочном файле и которое целиком (т.е. вместе с инициализатором) видно везде.

Это в частности означает, что для переменных комбинация inline static является избыточной: можно просто написать static с тем же эффектом.

READ ALSO
Слишком мало аргументов для вызова

Слишком мало аргументов для вызова

Только начал писать программу, и уже застрялВ 17 строке (5 снизу)

110
Как с помощью Clang собрать библиотеку из исходного кода на Windows

Как с помощью Clang собрать библиотеку из исходного кода на Windows

Что нужно сделать, чтобы получить статическую/динамическую GLFW (или любую другую, в которой имеются файлы makefile или/и cmakeliststxt) библиотеку 64-бит...

139
c++: способ передать параметры для конструктора

c++: способ передать параметры для конструктора

заранее извиняюсь за большую портянку в вопросе

128