Team LiB
Previous Section Next Section

7.6. Inline Functions

7.6. 内联函数

Recall the function we wrote on page 248 that returned a reference to the shorter of its two string parameters:

回顾在第 7.3.2 节编写的那个返回两个 string 形参中较短的字符串的函数:

     // find longer of two strings
     const string &shorterString(const string &s1, const string &s2)
     {
         return s1.size() < s2.size() ? s1 : s2;
     }

The benefits of defining a function for such a small operation include:

为这样的小操作定义一个函数的好处是:

  • It is easier to read and understand a call to shorterString than it would be to read and interpret an expression that used the equivalent conditional expression in place of the function call.

    阅读和理解函数 shorterString 的调用,要比读一条用等价的条件表达式取代函数调用表达式并解释它的含义要容易得多。

  • If a change needs to be made, it is easier to change the function than to find and change every occurrence of the equivalent expression.

    如果需要做任何修改,修改函数要比找出并修改每一处等价表达式容易得多。

  • Using a function ensures uniform behavior. Each test is guaranteed to be implemented in the same manner.

    使用函数可以确保统一的行为,每个测试都保证以相同的方式实现。

  • The function can be reused rather than rewritten for other applications.

    函数可以重用,不必为其他应用重写代码。

There is, however, one potential drawback to making shorterString a function: Calling a function is slower than evaluating the equivalent expression. On most machines, a function call does a lot of work: registers are saved before the call and restored after the return; the arguments are copied; and the program branches to a new location.

但是,将 shorterString 写成函数有一个潜在的缺点:调用函数比求解等价表达式要慢得多。在大多数的机器上,调用函数都要做很多工作;调用前要先保存寄存器,并在返回时恢复;复制实参;程序还必须转向一个新位置执行。

inline Functions Avoid Function Call Overhead

inline 函数避免函数调用的开销

A function specified as inline (usually) is expanded "in line" at each point in the program in which it is invoked. Assuming we made shorterString an inline function, then this call

将函数指定为 inline 函数,(通常)就是将它在程序中每个调用点上“内联地”展开。假设我们将 shorterString 定义为内联函数,则调用:

         cout << shorterString(s1, s2) << endl;

would be expanded during compilation into something like

在编译时将展开为:

         cout << (s1.size() < s2.size() ? s1 : s2)
              << endl;

The run-time overhead of making shorterString a function is thus removed.

从而消除了把 shorterString 写成函数的额外执行开销。

We can define shorterString as an inline function by specifying the keyword inline before the function's return type:

从而消除了把 shorterString 写成函数的额外执行开销。

     // inline version: find longer of two strings
     inline const string &
     shorterString(const string &s1, const string &s2)
     {
             return s1.size() < s2.size() ? s1 : s2;
     }

The inline specification is only a request to the compiler. The compiler may choose to ignore this request.

inline 说明对于编译器来说只是一个建议,编译器可以选择忽略这个。



In general, the inline mechanism is meant to optimize small, straight-line functions that are called frequently. Many compilers will not inline a recursive function. A 1,200-line function is also not likely to be explanded inline.

一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。大多数的编译器都不支持递归函数的内联。一个 1200 行的函数也不太可能在调用点内联展开。

Put inline Functions in Header Files

inline 函数放入头文件

Unlike other function definitions, inlines should be defined in header files.

内联函数应该在头文件中定义,这一点不同于其他函数。



To expand the code of an inline function at the point of call, the compiler must have access to the function definition. The function prototype is insufficient.

inline 函数的定义对编译器而言必须是可见的,以便编译器能够在调用点内联展开该函数的代码。此时,仅有函数原型是不够的。

An inline function may be defined more than once in a program as long as the definition appears only once in a given source file and the definition is exactly the same in each source file. By putting inline functions in headers, we ensure that the same definition is used whenever the function is called and that the compiler has the function definition available at the point of call.

inline 函数可能要在程序中定义不止一次,只要 inline 函数的定义在某个源文件中只出现一次,而且在所有源文件中,其定义必须是完全相同的。把 inline 函数的定义放在头文件中,可以确保在调用函数时所使用的定义是相同的,并且保证在调用点该函数的定义对编译器可见。

Whenever an inline function is added to or changed in a header file, every source file that uses that header must be recompiled.

在头文件中加入或修改 inline 函数时,使用了该头文件的所有源文件都必须重新编译。



Exercises Section 7.6

Exercise 7.29:

Which one of the following declarations and definitions would you put in a header? In a program text file? Explain why.

对于下面的声明和定义,你会将哪个放在头文件,哪个放在程序文本文件呢?为什么?

     (a) inline bool eq(const BigInt&, const BigInt&) {...}
     (b) void putValues(int *arr, int size);

Exercise 7.30:

Rewrite the is Shorter function from page 235 as an inline function.

第 7.2.2 节的函数 is Shorter 改写为 inline 函数。


Team LiB
Previous Section Next Section