C++内联函数和上下文特定优化



我在Scott Meyers的Effective c++书中读到:

当你内联一个函数时,你可以让编译器在函数体上执行特定于上下文的优化。这样的优化对于普通的函数调用是不可能的。

现在的问题是:什么是特定于上下文的优化,为什么它是必要的?

我不认为"特定于上下文的优化"是一个定义的术语,但我认为它基本上意味着编译器可以分析调用地点和周围的代码,并使用这些信息来优化函数。

这里有一个例子。当然,它是人为的,但它应该展示了这个想法:

功能:

int foo(int i)
{
  if (i < 0) throw std::invalid_argument("");
  return -i;
}

调用网站:

int bar()
{
  int i = 5;
  return foo(i);
}

如果单独编译foo,它必须包含比较和异常抛出代码。如果它内联在bar中,编译器会看到以下代码:

int bar()
{
  int i = 5;
  if (i < 0) throw std::invalid_argument("");
  return -i;
}

任何合理的优化器都会将其计算为

int bar()
{
  return -5;
}

如果编译器选择内联函数,它将用函数体替换对该函数的函数调用。现在在调用函数体中有更多代码需要优化。因此,它通常会产生更好的代码。

想象一下:

bool callee(bool a){
   if(a) return false;
   else return true;
}
void caller(){
   if(callee(true)){
       //Do something
   }   
   //Do something
}
一旦内联,代码将像这样(近似地):
void caller(){
   bool a = true;
   bool ret;
   if(a) ret = false;
   else ret = true;
   if(ret){
       //Do something
   }   
   //Do something
}

还可以进一步优化:

void caller(){
   if(false){
       //Do something
   }   
   //Do something
}

然后到:

void caller(){
   //Do something
}

函数现在小得多了,你没有函数调用的成本,特别是(关于这个问题)分支的成本。

假设函数为

void fun( bool b) { if(b) do_sth1(); else do_sth2(); }

,它在带有预定义的false参数

的上下文中被调用
bool param = false;
...
fun( param);

则编译器可以将函数体缩减为

...
do_sth2();

我不认为上下文特定的优化意味着特定的东西,你可能找不到确切的定义。

很好的例子是一些类属性的经典getter,没有内联程序必须:

  1. 跳转到getter主体
  2. 移动值到注册表(eaxx86在windows下与默认的Visual studio设置)
  3. 跳转回被调用对象
  4. eax的值移动到本地变量

而使用内联可以跳过几乎所有的工作,直接将值移动到局部变量。

优化严格依赖于编译器,但可能会发生很多事情(变量分配可能会被跳过,代码可能会重新排序等等…但是你总是保存call/jump,这是一个昂贵的指令。

相关内容

  • 没有找到相关文章

最新更新