inline
specifier
Спецификатор inline , используемый в decl-specifier-seq функции, объявляет функцию как inline-функцию .
Функция, определённая полностью внутри class/struct/union definition , независимо от того, является ли она функцией-членом или не-членом friend функцией, неявно является inline функцией если она не прикреплена к named module (since C++20) .
|
Функция, объявленная constexpr или consteval (since C++20) при первом объявлении, неявно является встроенной функцией. Удалённая функция неявно является встроенной функцией: её (удалённое) определение может появляться более чем в одной единице трансляции. |
(since C++11) |
|
Спецификатор inline при использовании в decl-specifier-seq переменной со статической продолжительностью хранения (статический член класса или переменная в области пространства имён), объявляет переменную встроенной переменной . Статический член данных, объявленный constexpr при первом объявлении, неявно является встроенной переменной. |
(since C++17) |
Содержание |
Объяснение
Встроенная функция или встроенная переменная (начиная с C++17) обладает следующими свойствами:
- Определение встроенной функции или переменной (since C++17) должно быть доступно в единице трансляции, где оно используется (не обязательно до точки использования).
- Встроенная функция или переменная (since C++17) с внешним связыванием (например, не объявленная как static ) обладает следующими дополнительными свойствами:
-
- В программе может быть несколько определений встраиваемой функции или переменной (since C++17) при условии, что каждое определение появляется в отдельной единице трансляции и (для нестатических встраиваемых функций и переменных (since C++17) ) все определения идентичны. Например, встраиваемая функция или встраиваемая переменная (since C++17) может быть определена в заголовочном файле, который включается в несколько исходных файлов.
- Она должна быть объявлена inline в каждой единице трансляции.
- Она имеет одинаковый адрес в каждой единице трансляции.
В встроенной функции,
- Функционально-локальные статические объекты во всех определениях функций являются общими для всех единиц трансляции (все они ссылаются на один и тот же объект, определённый в одной единице трансляции).
- Типы, определённые во всех определениях функций, также одинаковы во всех единицах трансляции.
|
Встроенные const-переменные на уровне пространства имен имеют внешнюю линковку по умолчанию (в отличие от невстроенных не-volatile const-квалифицированных переменных). |
(since C++17) |
Первоначальное предназначение ключевого слова inline заключалось в указании оптимизатору, что встраивание функции предпочтительнее вызова функции, то есть вместо выполнения инструкции вызова функции для передачи управления телу функции, выполняется копия тела функции без генерации вызова. Это позволяет избежать накладных расходов, создаваемых вызовом функции (передача аргументов и получение результата), но может привести к увеличению размера исполняемого файла, поскольку код функции должен повторяться многократно.
Поскольку подстановка inline-функций ненаблюдаема в стандартной семантике, компиляторы могут свободно использовать inline-подстановку для любой функции, не помеченной inline , и могут генерировать вызовы функций для любой функции, помеченной inline . Эти оптимизационные решения не изменяют правила, касающиеся множественных определений и общих статических переменных, перечисленных выше.
|
Поскольку значение ключевого слова inline для функций стало означать «разрешено несколько определений» вместо «предпочтительна подстановка» начиная с C++98, это значение было расширено на переменные. |
(since C++17) |
Примечания
Если встроенная функция или переменная (начиная с C++17) с внешним связыванием определена по-разному в разных единицах трансляции, программа является некорректной, диагностика не требуется.
Спецификатор inline не может использоваться с объявлением функции или переменной (начиная с C++17) в области видимости блока (внутри другой функции).
Спецификатор inline не может переобъявлять функцию или переменную (начиная с C++17) , которая уже была определена в единице трансляции как не-inline.
Неявно сгенерированные функции-члены и любые функции-члены, объявленные как defaulted при первом объявлении, являются inline, как и любая другая функция, определённая внутри определения класса.
Если встроенная функция объявлена в разных единицах трансляции, совокупные наборы аргументов по умолчанию должны быть одинаковыми в конце каждой единицы трансляции.
В языке C встраиваемые функции не обязаны быть объявлены inline в каждой единице трансляции (максимум одна может быть не- inline или extern inline ), определения функций не обязаны быть идентичными (но поведение программы не определено, если оно зависит от того, какая версия вызывается), а статические объекты на уровне функции различаются между разными определениями одной и той же функции.
|
См. статические члены данных для дополнительных правил о встроенных статических членах. Встроенные переменные устраняют основное препятствие для упаковки C++ кода в виде библиотек только с заголовочными файлами. |
(начиная с C++17) |
| Макрос тестирования возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_inline_variables
|
201606L
|
(C++17) | Inline variables |
Ключевые слова
Пример
Заголовочный файл "example.h":
#ifndef EXAMPLE_H #define EXAMPLE_H #include <atomic> // функция, включенная в несколько исходных файлов, должна быть inline inline int sum(int a, int b) { return a + b; } // переменная с внешней линковкой, включенная в несколько исходных файлов, должна быть inline inline std::atomic<int> counter(0); #endif
Исходный файл #1:
#include "example.h" int a() { ++counter; return sum(1, 2); }
Исходный файл #2:
#include "example.h" int b() { ++counter; return sum(3, 4); }
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 281 | C++98 |
объявление функции-друга могло использовать спецификатор inline
даже если дружественная функция не является встроенной функцией |
запретить такое использование |
| CWG 317 | C++98 |
функция могла быть объявлена inline даже если она имеет невстроенное
определение в той же единице трансляции до объявления |
программа является некорректно
сформированной в этом случае |
| CWG 765 | C++98 |
тип, определенный во встроенной функции, может
отличаться в разных единицах трансляции |
такие типы одинаковы
во всех единицах трансляции |
| CWG 1823 | C++98 |
строковые литералы во всех определениях встроенной
функции были общими для всех единиц трансляции |
требование удалено в связи с
согласованностью и реализациями |
| CWG 2531 | C++17 |
статический член данных мог быть неявно inline даже если
он не был объявлен constexpr при первом объявлении |
он не является неявно
inline в этом случае |
Смотрите также
|
Документация C
для
inline
|