inline спецификатор
Спецификатор inline, используемый в последовательности decl-specifier-seq функции, объявляет функцию как встроенную функцию.
Функция, определённая полностью внутри определения класса/структуры/объединения, будь то член-функция или не являющаяся членом функция friend, неявно является встроенной функцией за исключением случаев, когда она прикреплена к именованному модулю(с C++20).
| Функция, объявленная constexpr или Удаленная функция неявно является встроенной функцией: её (удалённое) определение может появиться более чем в одной единице трансляции. | (с C++11) |
| Спецификатор inline, используемый в последовательности decl-specifier-seq переменной со статической продолжительностью существования (статический член класса или переменная области видимости пространства имён), объявляет переменную как встроенную переменную. Статический член данных, объявленный constexpr в своём первом объявлении, неявно является встроенной переменной. | (с C++17) |
Объяснение
Встроенная функция или встроенная переменная(с C++17) обладает следующими свойствами:
- Определение встроенной функции или переменной(с C++17) должно быть доступно в единице трансляции, где оно используется (не обязательно до точки использования).
- Встроенная функция или переменная(с C++17) с внешней связью (например, не объявленная как static) имеет следующие дополнительные свойства:
- В программе может быть несколько определений встроенной функции или переменной(с C++17), при условии, что каждое определение находится в разных единицах трансляции и (для нестатических встроенных функций и переменных(с C++17)) все определения идентичны. Например, встроенную функцию или встроенную переменную(с C++17) можно определить в заголовочном файле, который подключается в несколько исходных файлов.
- Она должна быть объявлена как inline в каждой единице трансляции.
- Она имеет один и тот же адрес в каждой единице трансляции.
Для встроенной функции,
- Локальные статические объекты во всех определениях функции совместно используются во всех единицах трансляции (они все ссылаются на один и тот же объект, определённый в одной единице трансляции).
- Типы, определённые во всех определениях функции, также одинаковы во всех единицах трансляции.
| Встроенные константные переменные в области видимости пространства имён по умолчанию имеют внешнюю связь (в отличие от не встроенных не волатильных константных переменных). | (с C++17) |
Первоначальным назначением ключевого слова inline было служить указателем для оптимизатора, что встраивание функции предпочтительнее вызова функции, то есть вместо выполнения инструкции вызова функции для передачи управления телу функции, копируется тело функции без генерации вызова. Это позволяет избежать накладных расходов, создаваемых вызовом функции (передача аргументов и получение результата), но может привести к увеличению исполняемого файла, так как код функции должен повторяться несколько раз.
Так как это значение ключевого слова inline не является обязательным, компиляторы могут использовать встраивание для любой функции, не помеченной как inline, и могут генерировать вызовы функций для любой функции, помеченной как inline. Эти варианты оптимизации не изменяют правил, касающихся множественных определений и общих статических переменных, указанных выше.
| Поскольку значение ключевого слова inline для функций стало означать «разрешение на несколько определений», а не «преимущество встраивания», это значение было распространено на переменные. | (с C++17) |
Примечания
Если встроенная функция или переменная(с C++17) с внешней связью определена по-разному в разных единицах трансляции, программа считается некорректной, без необходимости диагностики.
Спецификатор inline не может использоваться с объявлением функции или переменной(с C++17) в области блока (внутри другой функции).
Спецификатор inline не может повторно объявить функцию или переменную(с C++17), которая уже была определена в единице трансляции как не встроенная.
Неявные функции-члены и любые функции-члены, объявленные как по умолчанию в своём первом объявлении, являются встроенными, как и любая другая функция, определённая внутри определения класса.
Если встроенная функция объявлена в разных единицах трансляции, накопленные наборы значений по умолчанию должны быть одинаковыми в конце каждой единицы трансляции.
В C, встроенные функции не обязательно должны быть объявлены inline в каждой единице трансляции (как максимум одна может быть не inline или extern inline), определения функции не обязательно должны быть идентичны (но поведение программы не определено, если оно зависит от того, какой вызов используется), а локальные статические переменные отличаются между разными определениями одной и той же функции.
| См. статические члены данных для дополнительных правил относительно статических членов inline. Встроенные переменные устраняют основное препятствие для упаковки кода C++ в заголовочные библиотеки. | (с C++17) |
| Feature-test macro | Значение | Std | Функция |
|---|---|---|---|
__cpp_inline_variables | 201606L | (C++17) | Встроенные переменные |
Пример
Заголовок "example.h":
#ifndef EXAMPLE_H
#define EXAMPLE_H
#include <atomic>
// function included in multiple source files must be inline
inline int sum(int a, int b)
{
return a + b;
}
// variable with external linkage included in multiple source files must be 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 | Применён к | Поведение, как опубликовано | Правильное поведение |
|---|---|---|---|
| CWG 281 | C++98 | объявление функции-друга могло использовать спецификатор inline даже если дружественная функция не является встроенной функцией | запретить такие использования |
| CWG 317 | C++98 | функция могла быть объявлена как встроенная, даже если у неё есть не встроенное определение в той же единице трансляции перед объявлением | в этом случае программа некорректна |
| CWG 765 | C++98 | тип, определённый в встроенной функции, мог быть разным в разных единицах трансляции | такие типы одинаковы во всех единицах трансляции |
| CWG 1823 | C++98 | строковые литералы во всех определениях встроенной функции совместно использовались во всех единицах трансляции | требование удалено из-за согласованности и реализаций |
| CWG 2531 | C++17 | статический член данных мог быть неявно встроенным, даже если он не был объявлен constexpr в своём первом объявлении | в этом случае он не является неявно встроенным |
См. также
Документация C для inline |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/inline