C++ 中的内联函数
默认情况下,类定义中定义的所有成员函数都声明为 Inline。让我们对这些功能有一些背景知识。
你必须记住来自 C 语言的预处理器。C++ 中的内联函数和 C 语言中的宏做同样的事情。预处理器/宏没有在 C++ 中使用,因为它们有一些缺点。
C++ 中预处理程序/宏的缺点
在宏中,我们在程序开始时用它的值定义某个变量,在程序中我们使用那个变量的任何地方,它都被编译时的值所代替。
1)间距问题
让我们试着用一个例子来理解这个问题,
#define G (y) (y+1)
这里我们定义了一个名为G(y)
的宏,在编译时用它的值来代替,也就是(y+1)
。但是,当我们称之为G(y)
时,实际上会发生什么,
G(1) // Macro will replace it
预处理器会像这样展开它,
(y) (y+1) (1)
你一定在想为什么会这样,这是因为宏定义中的间距。因此,带有多个表达式的大函数永远不能与宏一起使用,所以在 C++ 中引入了 Inline 函数。
2)复杂论证问题
在某些情况下,这样的宏表达式对某些参数很有效,但是当我们使用复杂的参数时,问题就开始出现了。
#define MAX(x,y) x>y?1:0
如果我们用这个表达,
if(MAX(a&0x0f, 0x0f)) // Complex Argument
宏将扩展到,
if( a&0x0f > 0x0f ? 1:0)
这里运算符的优先级会导致问题,因为&
的优先级比>
低,所以宏观评估会让你大吃一惊。这个问题可以通过使用括号来解决,但是对于更大的表达式,问题还是会出现。
3)无法访问类的私有成员
使用宏,在 C++ 中,您永远无法访问私有变量,因此您必须将这些成员公开,这将暴露实现。
class Y
{
int x;
public :
#define VAL(Y::x) // Its an Error
}
C++ 中的内联函数
内联函数是实际的函数,在编译过程中会被复制到各处,就像预处理器宏一样,这样就减少了函数调用的开销。默认情况下,类定义中定义的所有函数都是内联的,但是您也可以使用关键字将任何非类函数内联到它们上面。
对于内联函数,声明和定义必须一起完成。例如,
inline void fun(int a)
{
return a++;
}
关于内联函数的几个要点
- 我们必须保持内联函数小,小的内联函数有更好的效率。
- 内联函数确实提高了效率,但是我们不应该让所有的函数都内联。因为如果我们内联大函数,可能会导致代码膨胀,也可能会影响速度。
- 因此,建议使用范围解析
::
运算符在类定义之外定义大型函数,因为如果我们在类定义之内定义这样的函数,那么它们会自动内联。 - 内联函数由编译器保存在符号表中,对这些函数的所有调用都在编译时进行。
C++ 中的 Getter 和 Setter 函数
我们已经在访问类内部的私有数据变量的主题中研究过这一点。我们使用内联的访问函数来实现这一点。
class Auto
{
// by default private
int price;
public:
// getter function for variable price
int getPrice()
{
return price;
}
// setter function for variable price
void setPrice(int x)
{
i=x;
}
};
这里getPrice()
和setPrice()
是内联函数,用于访问类Auto
的私有数据成员。函数getPrice()
,在这种情况下称为 Getter 或 Accessor 函数,函数setPrice()
是 Setter 或 Mutator 函数。
也可以有重叠的存取函数和变异函数。我们将在下一个主题中研究重载函数。
内联函数的局限性
- 大型内联函数会导致缓存未命中,并对性能产生负面影响。
- 编译时在代码中到处复制函数体的编译开销,对于小程序来说可以忽略不计,但是对于大代码库来说却有所不同。
- 另外,如果我们需要函数在程序中的地址,编译器就不能对这些函数进行内联。因为为了给函数提供地址,编译器必须给它分配存储空间。但是内联函数没有存储空间,它们保存在符号表中。
理解 C++ 中的前向引用
所有内联函数都由编译器在类声明的末尾进行评估。
class ForwardReference
{
int i;
public:
// call to undeclared function
int f()
{
return g()+10;
}
int g()
{
return i;
}
};
int main()
{
ForwardReference fr;
fr.f();
}
您一定认为这将导致编译时错误,但在这种情况下,它会起作用,因为在类声明的右大括号之前,不会计算类中的内联函数。