C++ 内联函数与预处理器宏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1137575/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:59:12  来源:igfitidea点击:

Inline functions vs Preprocessor macros

c++cmacrosinline

提问by Subodh

How does an inline function differ from a preprocessor macro?

内联函数与预处理器宏有何不同?

回答by LBushkin

Preprocessor macros are just substitution patterns applied to your code. They can be used almost anywhere in your code because they are replaced with their expansions before any compilation starts.

预处理器宏只是应用于您的代码的替换模式。它们几乎可以在您的代码中的任何地方使用,因为它们在任何编译开始之前就被它们的扩展替换了。

Inline functions are actual functions whose body is directly injected into their call site. They can only be used where a function call is appropriate.

内联函数是其主体直接注入其调用站点的实际函数。它们只能在适合函数调用的地方使用。

Now, as far as using macros vs. inline functions in a function-like context, be advised that:

现在,就在类似函数的上下文中使用宏与内联函数而言,请注意:

  • Macros are not type safe, and can be expanded regardless of whether they are syntatically correct - the compile phase will report errors resulting from macro expansion problems.
  • Macros can be used in context where you don't expect, resulting in problems
  • Macros are more flexible, in that they can expand other macros - whereas inline functions don't necessarily do this.
  • Macros can result in side effects because of their expansion, since the input expressions are copied wherever they appear in the pattern.
  • Inline function are not always guaranteed to be inlined - some compilers only do this in release builds, or when they are specifically configured to do so. Also, in some cases inlining may not be possible.
  • Inline functions can provide scope for variables (particularly static ones), preprocessor macros can only do this in code blocks {...}, and static variables will not behave exactly the same way.
  • 宏不是类型安全的,无论它们在语法上是否正确都可以扩展 - 编译阶段将报告由宏扩展问题导致的错误。
  • 宏可以在您不期望的上下文中使用,从而导致问题
  • 宏更灵活,因为它们可以扩展其他宏——而内联函数不一定这样做。
  • 宏可能会由于其扩展而导致副作用,因为输入表达式会在它们出现在模式中的任何地方进行复制。
  • 内联函数并不总是保证被内联 - 一些编译器只在发布版本中这样做,或者当它们被专门配置为这样做时。此外,在某些情况下,内联可能是不可能的。
  • 内联函数可以为变量(尤其是静态变量)提供范围,预处理器宏只能在代码块 {...} 中执行此操作,并且静态变量的行为方式不会完全相同。

回答by ThibThib

First, the preprocessor macros are just "copy paste" in the code before the compilation. So there is no type checking, and some side effectscan appear

首先,预处理器宏只是编译前代码中的“复制粘贴”。所以没有类型检查,并且会出现一些副作用

For example, if you want to compare 2 values:

例如,如果要比较 2 个值:

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

The side effects appear if you use max(a++,b++)for example (aor bwill be incremented twice). Instead, use (for example)

max(a++,b++)例如,如果您使用(ab将增加两次),则会出现副作用。相反,使用(例如)

inline int max( int a, int b) { return ((a<b)?b:a); }

回答by DataCruncher

The Inline function are expanded by the compiler where as the macros are expanded by the Preprocessor, which is mere textual substitution.Hence

Inline 函数由编译器扩展,而宏由预处理器扩展,这仅仅是文本替换。 因此

  • There is no type checking during macro invocation while type checking is done during function call.

  • Undesired results and inefficiency may occur during macro expansion due to reevaluation of arguments and order of operations. For example

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);
    

    would result in

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
    
  • The macro arguments are not evaluated before macro expansion

    #define MUL(a, b) a*b
    int main()
    {
      // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
      printf("%d", MUL(2+3, 3+5));
     return 0;
    }
    // Output: 16`
    
  • The return keyword cannot be used in macros to return values as in the case of functions.

  • Inline functions can be overloaded

  • The tokens passed to macros can be concatenated using operator ## called Token-Pasting operator .

  • Macros are generally used for code reuse where as inline functions are used to eliminate the time overhead (excess time) during function call(avoiding a jump to a subroutine).

  • 在宏调用期间没有类型检查,而在函数调用期间进行类型检查。

  • 由于重新评估参数和操作顺序,在宏扩展期间可能会出现不希望的结果和低效率。例如

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);
    

    会导致

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
    
  • 在宏扩展之前不评估宏参数

    #define MUL(a, b) a*b
    int main()
    {
      // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
      printf("%d", MUL(2+3, 3+5));
     return 0;
    }
    // Output: 16`
    
  • 不能在宏中使用 return 关键字来返回值,就像函数一样。

  • 内联函数可以重载

  • 传递给宏的标记可以使用称为 Token-Pasting operator 的运算符 ## 连接。

  • 宏通常用于代码重用,其中内联函数用于消除函数调用期间的时间开销(多余时间)(避免跳转到子例程)。

回答by sharptooth

The key difference is type checking. The compiler will check whether what you pass as input values is of types that can be passed into the function. That's not true with preprocessor macros - they are expanded prior to any type checking and that can cause severe and hard to detect bugs.

主要区别在于类型检查。编译器将检查您作为输入值传递的内容是否属于可以传递到函数中的类型。预处理器宏并非如此——它们在任何类型检查之前进行了扩展,这可能会导致严重且难以检测的错误。

Hereare several other less obvious points outlined.

这里列出了其他几个不太明显的要点。

回答by RichieHindle

To add another difference to those already given: you can't step through a #definein the debugger, but you can step through an inline function.

为已经给出的那些添加另一个区别:您不能#define在调试器中单步执行 a ,但可以单步执行内联函数。

回答by Kirill V. Lyadvinsky

Macros are ignoring namespaces. And that makes them evil.

宏忽略命名空间。这使他们变得邪恶。

回答by Ahmad

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.

  • 内联函数遵循对正常函数强制执行的所有类型安全协议。
  • 内联函数使用与任何其他函数相同的语法指定,除了它们在函数声明中包含 inline 关键字。
  • 作为参数传递给内联函数的表达式被评估一次。
  • 在某些情况下,作为参数传递给宏的表达式可以计算多次。 http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx

  • 宏在预编译时扩展,您不能将它们用于调试,但您可以使用内联函数。

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

--好文章:http://www.codeguru.com/forum/showpost.php?p= 1093923&postcount=1

;

;

回答by Michael Donohue

An inline function will maintain value semantics, whereas a preprocessor macro just copies the syntax. You can get very subtle bugs with a preprocessor macro if you use the argument multiple times - for example if the argument contains mutation like "i++" having that execute twice is quite a surprise. An inline function will not have this problem.

内联函数将维护值语义,而预处理器宏只是复制语法。如果多次使用该参数,则预处理器宏可能会出现非常微妙的错误 - 例如,如果该参数包含像“i++”这样的突变,执行两次是相当令人惊讶的。内联函数不会有这个问题。

回答by heeen

A inline functuion behaves syntactically just like a normal function, providing type safety and a scope for function local variables and access to class-members if it is a method. Also when calling inline methods you must adhere to private/protected restrictions.

内联函数在语法上的行为就像普通函数一样,提供类型安全和函数局部变量的作用域以及对类成员的访问(如果它是一个方法)。此外,在调用内联方法时,您必须遵守私有/受保护的限制。

回答by Brian

From the perspective of coding, an inline function is like a function. Thus, the differences between an inline function and a macro are the same as the differences between a function and a macro.

从编码的角度来看,内联函数就像一个函数。因此,内联函数和宏之间的差异与函数和宏之间的差异相同。

From the perspective of compiling, an inline function is similar to a macro. It is injected directly into the code, not called.

从编译的角度来看,内联函数类似于宏。它直接注入到代码中,而不是调用。

In general, you should consider inline functions to be regular functions with some minor optimization mixed in. And like most optimizations, it is up to the compiler to decide if it actually cares to apply it. Often the compiler will happily ignore any attempts by the programmer to inline a function, for various reasons.

通常,您应该将内联函数视为混合了一些次要优化的常规函数​​。与大多数优化一样,由编译器决定它是否真的关心应用它。出于各种原因,编译器通常会很乐意忽略程序员内联函数的任何尝试。