Efficient C++ 第八章 内联基础

转自
http://blog.chinaunix.net/uid-25872711-id-3030347.html

Efficient C++ 第八章 内联基础


    这一章看下来,明显发现了自己基础知识方面的薄弱,学习的越是深入就越能发现自己的无知。
什么是内联
  内联用一种类似于宏的展开方式代替方法调用,它在在主调函数内部展开。可以用两种方式建议函数内联(因为内联是编译器可选的),一种是inline关键字,一种是在头文件定义方法。
  由于内联函数的代码需要被展开,所以内联函数的任何修改都要求对程序进行重新编译。
int main ()
{
    GatedInt gi;
    gi.set(12);
    cout << gi.get();
}

    假设get()和set为非内联函数,那么程序需要进行set,get,cout<<三次调用。在头两次调用中,完成函数调用和返回需要工作的开销比函数内部的实际执行代码开销可能会多一个数量级。
  相反,内联的get和set,使程序只包含cout<<操作符的调用,逻辑上以上代码会编译成如下伪码:
int main ()
{
    GatedInt gi;
    {
        gi::x = 12;
    }
    int temp = gi::x;
    cout << temp;
}


    实际上编译器会做更好的优化,可以简化成:
int main ()
{
    cout << 12;
}

函数内联展开后,内联函数的参数和返回值都成为其调用点处理的局部对象,避免了函数调用。并且不光如此,调用间优化,可以使内联函数编译后极精简。
  
方法调用代价
  深层次的讲述了,函数调用的复杂,使用函数调用栈的把参数入栈,返回值出栈等等。涉及比较底层,只能看懂大意,C语言需要深入重学一遍了。
  这里得出结论,函数调用的开销比较大。

为何使用内联
  通过内联,可以在不进行任何重写的情况下,相对较大的提升系统性能。

内联详述
  内联是编译器可选的,同时一个优化的编译器会内联一些未声明为内联的函数。书的作者认为内联最终会成为基于编译器的优化,无需工程师去思考。

内联的性能
int x::get_y()
{
    return y;
}


    上面方法本身开销可能只有3,4个时钟周期,但如果调用它的话,它会产生大约20个时间周期的开销。如果内联该方法,那么它将只消耗1或2个时钟周期(比原来小,是因为不再有调用、返回开销)。也就是说内联后速度能提升10倍,同时开销节省的时间周期都可以对应一条指令,也就是说我们还缩小了代码长度。
  通过测试程序,也得出结论,内联使程序明显加快并且程序更小一些。

  本书用三章详细讲述了内联性能问题,
  第九章介绍编译器对内联代码层面的优化,内联的缺点,不是所有函数都适合内联。
  这里先跳过,记住内联的一个基本原则,简单的函数尽量内联。

猜你喜欢

转载自jacky-dai.iteye.com/blog/2307357