Чем отличается встроенная функция С++ от макроса Си?

124
19 февраля 2018, 03:21

Как я понял, встроенная функция в С++ это аналог макроса Си. Но в книге прочел, что встраиванием кода встроенной функции занимается компилятор, в то время как в Си макросы встраиваются препроцессором. Также макросы могут быть только однострочными, в то время, как встроенные функции впринципе не ограничены в размерах (хотя рекомедуется не делать встроееными функции более 2 строк кода длинной). Подозреваю это не все важные отличия.

Answer 1

Также макросы могут быть только однострочными

Это полуправда, ведь никто не мешает поставить обратный слэш (" \ ") и писать с новой строки, будто она - продолжение предыдущей

в то время, как встроенные функции впринципе не ограничены в размерах

Чем длиннее функция, тем меньше вероятность, что ее заинлайнит компилятор. Но, понятное дело, что компилятор не на строки ориентируется, а на операторы (с учетом оптимизации).

В общем случае стоит противопоставлять не просто inline-функции (ведь для современных компиляторов само ключевое слово inline - это не приказ и даже не рекомендация что-то там встраивать), а constexpr. У них, как (как и у глобальных констант, вместо #define-констант) есть ряд преимуществ:

  • Они более типобезопасны
  • Они учитывают области видимости
  • Более читаемый и предсказуемый результат благодаря тому, что аргументы вычисляются, а не подставляются

Конечно же за счет этого строгого контроля inline-функции не заменят макросы в некоторых аспектах (условная компиляция, какая-то часть кодогенерации), но в остальных - стоит отдавать им предпочтение.

Answer 2

Важное отличие макроса от inline (это скорее нужно перевести, как встраиваемая, а не встроенная) функции тем, что макрос отрабатывает на этапе препроцессинга. Раньше препроцессингом занимался отдельный процесс, сейчас компилятор обычно делает его сам. Но! на этапе препроцессинга есть только токены (грубо говоря, отдельные слова), но нет ни типов, ни переменных ни функций, ни блоков кода (то есть, правила видимости функций и переменных для макросов не работают - макрос доступен от точки объявлений и до конца файла или отмены макроса). Проверка корректности того, что получилось будет производиться только при компиляции. Поэтому возможны различные "чудеса". Например, классика (эта функция специально написана без скобок, но и они тут не помогут сильно)

#define max(a,b) a>b?a:b

И вызываем так

max(x+1, b++)

и дальше будет не совсем то, что ожидается.

Если же использовать inline функцию, то поведение будет очень предсказуемым.

В целом, компиляторы сейчас достаточно умные и сами умеют хорошо инлайнить, когда это уместно. Поэтому, в большинстве случаев это ключевое слово даже и не нужно.

Также макросы могут быть только однострочными

макросы могут быть столь угодно большими. обратный слеш в конце строки поможет в этом (главное, что бы после него не было пробелов или других символов кроме перевода строк).

Важно также то, что переменные, объявленные внутри inline живут до конца функции (или блока кода), а переменные, объявленные внутри макроса могут живут в вызывающей их функции. Из за этого возможны конфликты имен.

В целом, макросы и inline функции хоть и могут делать похожие вещи, это все таки достаточно разные инструменты. Макросы умеют такое, что inline функции никогда не смогут (классический пример - X макрос).

READ ALSO
Не работает консоль в Visual Studio 2017

Не работает консоль в Visual Studio 2017

Когда делаю отладку консоль включается, но в нее ничего не записываетсяЯ перекачивал Visual Studio 4 раза и все равно не работает

153
Фоновый ввод информации C++

Фоновый ввод информации C++

Как сделать так чтобы программа работала, скажем циклом, но ждала ввода информации? Допустим у нас есть бесконечный цикл, который перечисляет...

131
boost::log из динамической библиотеки

boost::log из динамической библиотеки

Есть проект который состоит из нескольких библиотекЗадумывается так, что все эти библиотеки должны писать в один лог файл

135