Подставляемые функции по сравнению с макросами Препроцессора

Мелкий copy:  Копирует членские значения с одного объекта в другого.

Глубокий Copy:        Копирует членские значения с одного объекта в другого.
                                          Любые объекты указателя дублированы и Глубоко Скопированы.

Пример:

class String
{
     int   size;
     char* data;
};

String  s1("Ace");   // s1.size = 3 s1.data=0x0000F000

String  s2 = shallowCopy(s1);
 // s2.size =3 s2.data = 0X0000F000
String  s3 = deepCopy(s1);
 // s3.size =3 s3.data = 0x0000F00F
 //                      (With Ace copied to this location.)
107
задан Jim Fell 9 August 2017 в 18:18
поделиться

10 ответов

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

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

Теперь, что касается использования макросов и встроенных функций в функционально-подобном контексте, имейте в виду, что:

  • Макросы небезопасны по типу и могут быть расширены независимо от того, являются ли они синтаксически правильными - фаза компиляции сообщит об ошибках, связанных с проблемами расширения макроса.
  • Макросы можно использовать в контексте, где вы не ожидаете, что приведет к проблемам
  • Макросы более гибкие, поскольку они может расширять другие макросы - в то время как встроенные функции не t обязательно сделайте это.
  • Макросы могут привести к побочным эффектам из-за их расширения, поскольку входные выражения копируются везде, где они появляются в шаблоне.
  • Встроенная функция не всегда гарантированно встроена - некоторые компиляторы делают только это в сборках выпуска или когда они специально настроены для этого. Кроме того, в некоторых случаях встраивание может оказаться невозможным.
  • Встроенные функции могут предоставлять область видимости для переменных (особенно статических), макросы препроцессора могут делать это только в блоках кода {...}, а статические переменные не будут вести себя точно так, как таким же образом.
120
ответ дан 24 November 2019 в 03:39
поделиться

inline functions are similar to macros (because the function code is expanded at the point of the call at compile time), inline functions are parsed by the compiler, whereas macros are expanded by the preprocessor. As a result, there are several important differences:

  • Inline functions follow all the protocols of type safety enforced on normal functions.
  • Inline functions are specified using the same syntax as any other function except that they include the inline keyword in the function declaration.
  • Expressions passed as arguments to inline functions are evaluated once.
  • In some cases, expressions passed as arguments to macros can be evaluated more than once. http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx

  • macros are expanded at pre-compile time, you cannot use them for debugging, but you can use inline functions.

-- good article: http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1

;

3
ответ дан 24 November 2019 в 03:39
поделиться

С точки зрения кодирования встроенная функция похожа на функцию. Таким образом, различия между встроенной функцией и макросом такие же, как и различия между функцией и макросом.

С точки зрения компиляции встроенная функция похожа на макрос. Он вводится непосредственно в код, а не вызывается.

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

0
ответ дан 24 November 2019 в 03:39
поделиться

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

Разница между встроенными функциями и макросами препроцессора относительно велика. Макросы препроцессора - это просто замена текста в конце концов. Вы отказываетесь от многих возможностей компилятора выполнять проверку проверки типов аргументов и возвращаемого типа. Оценка аргументов сильно отличается (если выражения, которые вы передаете в функции, имеют побочные эффекты, вам будет очень интересно провести время за отладкой). Существуют тонкие различия в том, где можно использовать функции и макросы. Например, если бы у меня было:

#define MACRO_FUNC(X) ...

Где MACRO_FUNC, очевидно, определяет тело функции. Следует проявлять особую осторожность, чтобы она работала правильно во всех случаях, когда функция может быть использована, например, плохо написанный MACRO_FUNC вызовет ошибку в

if(MACRO_FUNC(y)) {
 ...body
}

. Обычная функция может быть использована без проблем.

0
ответ дан 24 November 2019 в 03:39
поделиться

Встроенная функция будет поддерживать семантику значения, тогда как макрос препроцессора просто копирует синтаксис. Вы можете получить очень тонкие ошибки с макросом препроцессора, если вы используете аргумент несколько раз - например, если аргумент содержит мутацию типа «i ++», выполнение этого дважды является большим сюрпризом. У встроенной функции этой проблемы не будет.

2
ответ дан 24 November 2019 в 03:39
поделиться

Встроенная функция синтаксически ведет себя так же, как обычная функция, обеспечивая безопасность типов и область для локальных переменных функции и доступ к члены класса, если это метод. Также при вызове встроенных методов вы должны придерживаться частных / защищенных ограничений.

1
ответ дан 24 November 2019 в 03:39
поделиться

Макросы игнорируют пространства имен. И это делает их злыми.

8
ответ дан 24 November 2019 в 03:39
поделиться

Чтобы добавить еще одно отличие к уже приведенным: вы не можете пройти через #define в отладчике, но вы можете пройти через встроенную функцию.

11
ответ дан 24 November 2019 в 03:39
поделиться

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

Здесь описаны несколько других менее очевидных моментов.

12
ответ дан 24 November 2019 в 03:39
поделиться

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

Например, если вы хотите сравнить 2 значения:

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

Побочные эффекты появляются, если вы используете max (a ++, b ++) например ( a или b будут увеличены вдвое). Вместо этого используйте (например)

inline int max( int a, int b) { return ((a<b)?b:a); }
70
ответ дан 24 November 2019 в 03:39
поделиться