7.3 Неявная связь
В C++ существуют некоторые конструкции, которые требуют места в объектном файле, но не связаны однозначно с единым модулем трансляции. Мы говорим, что эти конструкции имеют «неявную связь». Обычно такие конструкции генерируются там, где они необходимы, хотя иногда мы можем поступить более хитро.
- Встроенные функции
-
Встроенные функции обычно определяются в заголовочном файле, который может включаться во многих разных трансляциях. В идеале они обычно могут быть встроены, но иногда необходима внедренная копия, если адрес функции взяли или если встроенность не удалась. В общем случае мы генерируем внедренную копию во всех модулях трансляции, где она необходима. В качестве исключения, мы генерируем только встроенные виртуальные функции с vtable, так как это всегда требует копии.
Локальные статические переменные и строковые константы, используемые во встроенной функции, также считаются имеющими неявную связь, так как они должны быть общими для всех встроенных и внедренных экземпляров функции.
- VTable
-
Виртуальные функции C++ в большинстве компиляторов реализуются с помощью таблицы поиска, известной как vtable. Vtable содержит указатели на виртуальные функции, предоставляемые классом, и каждый объект класса содержит указатель на его vtable (или vtables, в некоторых ситуациях множественного наследования). Если класс объявляет какие-либо не встроенные, не чистые виртуальные функции, первая из них выбирается в качестве «ключевого метода» для класса, и vtable генерируется только в модуле трансляции, где определен ключевой метод.
Примечание: Если выбранный ключевой метод позже определен как встроенный, vtable все равно генерируется в каждом модуле трансляции, который его определяет. Убедитесь, что все встроенные виртуальные функции объявлены встроенными в теле класса, даже если они там не определены.
-
type_infoобъекты -
C++ требует информации о типах, чтобы реализовать ‘dynamic_cast’, ‘typeid’ и обработку исключений. Для полиморфных классов (классов с виртуальными функциями) объект ‘type_info’ генерируется вместе с vtable, чтобы ‘dynamic_cast’ мог определить динамический тип объекта класса во время выполнения. Для всех других типов мы генерируем объект ‘type_info’ при его использовании: при применении ‘typeid’ к выражению, выбрасывании объекта или ссылке на тип в блоке catch или спецификации исключения.
- Шаблонные инстанциации
-
Большая часть изложенного в этом разделе также применима к шаблонным инстанциациям, но есть и другие варианты. См. Где шаблон?.
При использовании с GNU ld версии 2.8 или новее на ELF-системах, таких как GNU/Linux или Solaris 2, или на Microsoft Windows, дублируемые копии этих конструкций будут удалены во время компоновки. Это известно как поддержка COMDAT.
На целевых платформах, которые не поддерживают COMDAT, но поддерживают слабые символы, GCC использует их. Таким образом, одна копия перекрывает все остальные, но неиспользуемые копии по-прежнему занимают место в исполняемом файле.
Для целей, которые не поддерживают ни COMDAT, ни слабые символы, большинство сущностей с неявной связью генерируются как локальные символы, чтобы избежать ошибок дублирования определения от компоновщика. Однако это не происходит для локальных статических значений в встроенных функциях, так как наличие нескольких копий почти наверняка нарушит работу.
См. Объявления и определения в одном заголовочном файле для другого способа управления размещением этих конструкций.
Далее: Интерфейс C++, Предыдущее: Ограниченные указатели, Вверх: Расширения C++ [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-6.5.0/gcc/Vague-Linkage.html