C++开发初级


892 浏览 5 years, 3 months

6.5 内联方法

版权声明: 转载请注明出处 http://www.codingsoho.com/

内联方法

C++提供了这样一种能力:函数或者方法的调用可以不以生成代码(就像调用独立的代码块)的方式实现。相反,编译器会将方法体或者函数体直接插入到调用方法或者函数的位置。这个过程称为内联(inline),具有这一行为的函数或者方法称为内联方法或者内联函数。内联比使用#define宏安全。

可以在方法或者函数定义的名称之前使用inline关键字将某个方法或者函数指定为内联的。例如,您可能想要让SpreadsheetCell类的访问方法成为内联的,在此情况下可以这样定义:

inline double SpreadsheetCell::getValue() const
{
    mNumAccesses++;
    return mValue;
}
inline string SpreadsheetCell::getString() const
{
    mNumAccesses++;
    return mString;
}

代码取自 SpreadsheetCellMethods\SpreadsheetCell.h

现在,编译器可以选择用实际的方法体替换getValue()以及getString()的调用,而不是生成代码进行函数调用。

需要注意,在所有调用了内联函数或者方法的源文件中,内联方法或者函数的定义必须有效。考虑这个问题:如果没有看到函数的定义,编译器如何替换函数体?因此,如果您编写了内联函数或者方法,应该将定义与原型一起放在头文件中。对于方法而言,这意味着将定义放在包含类定义的.h文件中。这个布置非常安全:链接器不会因为同一方法的多个定义而报错。

高级C++编译器不要求把内联方法的定义放在头文件中。例如,Microsoft VisualC++支持连接时代码生成(LTCG),会自动将较小的函数内联,哪怕这些函数没有声明为内联或者没有在头文件中定义也同样如此。当使用这类编译器的时候,可以利用这一点,从而不需要将定义放在头文件中。通过这种方法可以保持接口整洁,因为接口文件中看不到任何实现细节。

C++提供了另一种声明内联方法的语法,这一语法根本不需要使用inline关键字,而是直接将方法定义放在类定义中。下面是使用了这一语法的SpreadsheetCell类定义

class SpreadsheetCell
{
 public:
  double getValue() const {mNumAccesses++; return mValue; }
  string getString() const {mNumAccesses++; return mString; }
};

代码取自 SpreadsheetCellMethods\SpreadsheetCell.h

如果使用调试器单步调试内联函数的调用,某些高级的C++调试器会跳到头文件中内联函数实际的源代码处,造成了函数调用的假象,但实际上代码是内联的。

许多C++程序员了解inline方法的语法并使用这一语法,但不理解让方法内联的结果。首先,可以内联的方法受很多限制。编译器只会内联最简单的方法以及函数,如果将一个编译器不想内联的方法定义为内联,编译器会自动忽略这个指令。其次,大的内联方法会使得代码膨胀,在每个调用的地方都会重新生成方法体,从而增加了可执行程序的大小。

类似于Microsoft Visual C++的现代编译器在将方法内联之前,会考虑代码膨胀等指标,因此不会内联任何没有效益的方法。