Linkage
Linkage, или связывание – это свойство идентификатора, позволяющее компилятору в некоторых случаях создавать для нескольких одинаковых имен, объявленных в разных единицах трансляции, одну общую сущность. Вместе с областью видимости связывание определяет, из каких единиц трансляции и их блоков можно обратиться к сущности.
Существуют 4 вида связывания: no linkage, internal linkage, external linkage и module linkage.
No linkage
Следующие сущности, объявленные в блочной области видимости, имеют no linkage (иначе говоря, не имеют связывания):
- Локальные переменные, объявленные без спецификатора extern;
- Локальные классы и их методы;
- Другие идентификаторы, кроме имен функций, например псевдонимы или перечисления.
Для каждого имени без связывания компилятор сгенерирует отдельный объект.
Internal linkage
Если идентификатор имеет internal linkage (внутреннее связывание), то к нему можно обратиться из любого места текущей единицы трансляции. Для нескольких объявлений одинаковых имен с внутренним связыванием в одной единице трансляции компилятор сгенерирует один объект. Для одинаковых имен с internal linkage в разных единицах трансляции компилятор создаст разные объекты.
Следующие сущности, объявленные в пространстве имен, имеют внутреннее связывание:
- Переменные и функции, объявленные со спецификатором static;
- Нешаблонные переменные, объявленные со спецификатором const и без спецификаторов inline и volatile, а также без extern. Дополнительно такая переменная не должна быть объявлена с external linkage ранее;
- Члены анонимных объединений;
- Любые имена, объявленные в безымянном пространстве имен, в том числе объявленные со спецификатором extern.
External linkage
Идентификатор, имеющий external linkage (внешнее связывание), доступен из других единиц трансляции. Для одинаковых имен с внешним связыванием компилятор создаст один объект.
Идентификатор, имеющий external linkage, также имеет language linkage, благодаря которому связываются юниты трансляции, написанные на разных языках программирования.
Следующие сущности, объявленные в пространстве имен, имеют external linkage:
- Функции без спецификатора static;
- Переменные без спецификаторов const и extern;
- Переменные со спецификатором extern;
- Перечисления;
- Имена классов, их методов, а также вложенные классы и перечисления;
- Функции, объявленные внутри класса со спецификатором friend;
- Шаблоны, объявленные со спецификатором static, за исключением шаблонов функций и переменных.
Следующие сущности, объявленные в блочной области видимости, имеют external linkage:
- Переменные, объявленные со спецификатором extern;
- Функции.
Module linkage
Начиная со стандарта C++20, идентификатор может иметь module linkage (модульное связывание). Такой идентификатор доступен из единиц трансляции, входящих в тот же модуль, в котором он объявлен. Соответственно, для нескольких одинаковых объявлений одноименных сущностей с module linkage в рамках одного модуля будет создан один объект.
Module linkage имеют идентификаторы, прикрепленные к именованному модулю и не объявленные с ключевым словом export. Рассмотрим следующий код:
// cute_module_main.h
module CuteModule:moduleVariable;
int moduleVariable = 0;
// cute_module_calculator.h
export module CuteModule;
import :moduleVariable;
export int GetSquaredModuleVariable() {
return ::moduleVariable * ::moduleVariable;
}
Здесь переменная moduleVariable имеет module linkage.
0