Inline против constexpr?
С новым стандартом С++ 11, когда следует использовать ключевое слово inline
по ключевому слову constexpr
? Является ли ключевое слово constexpr
дополнительной оптимизацией по сравнению с inline
или просто утверждает, что вещи должны вычисляться во время компиляции?
Почему constexpr
работает в GCC в некоторых случаях, когда вызов не является постоянным, например вызов foo(x)
в переменной constexpr
? Является ли это ошибкой в GCC или действительно ли она является частью стандарта?
Ответы
Ответ 1
Утверждение, что что-то может быть вычислено во время компиляции, - довольно сильная оптимизация.
Вложение просто удаляет вызов функции, копируя/вставляя тело функции в сайт вызова. Тело функции еще должно быть выполнено, вы просто сохраняете накладные расходы на вызов функции.
Но если вы будете оценивать один и тот же код во время компиляции, он свободен во время выполнения.
Но ни inline
, ни constexpr
в основном не связаны с оптимизацией. inline
Основной целью является подавление правила с одним определением, так что функции могут быть определены в заголовках (что полезно для шаблонов и, кстати, также упрощает оптимизацию вложения)
И constexpr
существует, потому что это полезно в метапрограммировании, и, кстати, это может помочь компилятору лучше оптимизировать код, перемещая больше вычислений во время компиляции.
Ответ 2
Процитировать wikipedia:
С++ 0x представит ключевое слово constexpr, которое позволяет пользователю гарантировать, что конструктор функции или объекта является временем компиляции константа.
Отметьте функции inline, если они супер короткие. Mark выполняет функции constexpr, если результаты требуются во время компиляции. (Параметры шаблона или размеры массива). Я считаю, что функция может быть как при необходимости.
Функция константного выражения или конструктор можно вызвать с помощью параметры неконференции. Подобно тому, как литерал constexpr integer может быть присвоенный переменной non-constexpr, так же может быть функция constexpr вызывать с параметрами неконференсперса, а результаты, хранящиеся в не-constexpr. Ключевое слово допускает только возможность постоянства времени компиляции, когда все члены выражения constexpr.
Итак, GCC не является неправильным в этом.
Ответ 3
Пока inline
говорит компилятору: "Эта функция используется где-то в этой единицы перевода и не является общедоступной для других объектных файлов", вполне вероятно, что компилятор вставляет тело функции в вызывающий. constexpr
функции говорят компилятору "Эта функция не имеет побочных эффектов и не зависит от предварительных условий, отличных от самого параметра".
constexpr
переменные просто говорят: "Эта переменная не изменяется и ее данные могут быть включены в код". Однако имеет значение, если вы определяете переменную constexpr в функции статической или нестатической, например. если массив constexpr
нестатический, gcc просто перемещает данные с жестко закодированными mov
-Instructions в стек, а static constexpr
просто сохраняет данные в разделе .text
.
Лямбда-выражения без захвата, назначенные переменной, могут быть constexpr, кроме как с захватом, потому что без необходимости в них памяти не сохранять захват, и они работают как пустой класс с перегруженным operator()
(но их даже можно отливать на простое функциональные указатели с простым унарным плюсом: +[]{}
).