C++读书笔记

来源:互联网 发布:淘宝钱夫人雪梨 编辑:程序博客网 时间:2024/06/14 16:12
C++内联函数
一、内联和宏定义的区别
     (1)内联是与编译期有关,而宏是与预处理器有关,二者不在同一个时期处理。(PS:一般高级语言程序编译过程:预处理、编译、汇编、链接)。
       (2)  内联能够进行在函数替换的时候进行函数的类型,调用的参数等的匹配检查,而宏是不会的,宏另外有一个不佳 的地方在于会出现一些副作用。
       (3)  内联,对于任何内联函数,编译器在符号表内放入函数的声明(包括名字、参数类型、返回值类型)。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表内。在调用一个内联函数的时候,编译器首先检查调用是否正确(进行类型安全检查,或者进行自动类型转换)。如果正确,内联函数的代码会直接替换函数调用,省去了函数调用的开销。----------------------->以上是这段话的依据:“每一个non-inline member function 只会诞生一个函数实体。至于每一个拥有0个或1个定义的inline function 则会在每一个使用者(模块)身上产生一个函数实体。”
     (4)内联不一定会展开,而宏一定会展开。
二、显示和隐式内联
//显示(在类声明的内部声明,而在类声明外部定义)
#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
class display 
{
public:
int t;
public:
void output();
};
display object;

inline void display::output(void)
{
cout<<"i am "<<t<<"\n";
}
int main()
{
object.t = 10;
object.output();
return 0;
}
        
//隐式(在类声明的内部定义)
class display
{
       public:
            int t;
       public:
           inline void output(void)
            {
                    cout<<"i am "<<t; 
            }
};
三、内联禁忌
    (1)、内联inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。即inline无需放在函数的声明前,而且仅仅放在函数的声明前的话,也是不起作用的。
    (2)、循环递归、代码过大等都不适合使用inline,此时如果使用的话,编译器不认。
四、空间时间笔记

1)在空间上,一般印象是不采用内联,被调用函数的代码只有一份,调用它的地方使用call语句引用即可。而采用内联后,该函数的代码在所有调用其处都有一份拷贝,因此最后总的代码大小比采用内联前要大。但事实不总是这样的,如果一个函数a的体代码大小为AS,假设a函数在整个程序中被调用了n次,不采用内联时,对a的调用只有准备工作与善后工作两处会增加最后的代码量开销,即a函数相关的代码大小为:n * SS + AS。采用内联后,在各处调用点都需要将其函数体代码展开,即a函数相关的代码大小为n * AS。这样比较二者的大小,即比较(n * SS + AS)与(n*AS)的大小。考虑到n一般次数很多时,可以简化成比较SS与AS的大小。这样可以得出大致结论,如果被内联函数自己的函数体代码量比因为函数调用的准备与善后工作引入的代码量大,内联后程序的代码量会变大;相反,当被内联函数的函数体代码量比因为函数调用的准备与善后工作引入的代码量小,内联后程序的代码量会变小。这里还没有考虑内联的后续情况,即编译器可能因为获得的信息更多,从而对调用函数的优化做得更深入和彻底,致使最终的代码量变得更小。

(2)在时间上,一般而言,每处调用都不再需要做函数调用的准备与善后工作。另外内联后,编译器在做优化时,看到的是调用函数与被调用函数连成的一大块代码。即获得的代码信息更多,此时它对调用函数的优化可以做得更好。最后还有一个很重要的因素,即内联后调用函数体内需要执行的代码是相邻的,其执行的代码都在同一个页面或连续的页面中。如果没有内联,执行到被调用函数时,需要跳到包含被调用函数的内存页面中执行,而被调用函数所属的页面极有可能当时不在物理内存中。这意味着,内联后可以降低“缺页”的几率,知道减少“缺页”次数的效果远比减少一些代码量执行的效果。另外即使被调用函数所在页面可能也在内存中,但是因为与调用函数在空间上相隔甚远,所以可能会引起“cache miss”,从而降低执行速度。因此总的来说,内联后程序的执行时间会比没有内联要少。即程序的速度更快,这也是因为内联后代码的空间 “locality”特性提高了。但正如上面分析空间影响时提到的,当AS远大于SS,且n非常大时,最终程序的大小会比没有内联时要大很多。代码量大意味着用来存放代码的内存页也会更多,这样因为执行代码而引起的“缺页”也会相应增多。如果这样,最终程序的执行时间可能会因为大量的“缺页”而变得更多,即程序的速度变慢。这也是为什么很多编译器对于函数体代码很多的函数,会拒绝对其进行内联的请求。即忽略“inline”关键字,而对如同普通函数那样编译。

综合上面的分析,在采用内联时需要内联函数的特征。比如该函数自己的函数体代码量,以及程序执行时可能被调用的次数等。当然,判断内联效果的最终和最有效的方法还是对程序的大小和执行时间进行实际测量,然后根据测量结果来决定是否应该采用内联,以及对哪些函数进行内联。