内联函数FAQ

来源:互联网 发布:淘宝图片很不清楚 编辑:程序博客网 时间:2024/04/30 12:38
[9]   内联函数 
(part   of   c++   faq   lite,   copyright   ?   1991-96,   marshall   cline,   cline@parashift.com) 

-------------------------------------------------------------------------------- 

faqs   in   section   [9]: 
[9.1]   内联函数是什么? 
[9.2]   内联函数是如何在安全和速度上取得折衷? 
[9.3]   为什么我应该用内联函数?而不是原来清晰的   #define   宏? 
[9.4]   如何告诉编译器使非成员函数成为内联函数? 
[9.5]   如何告诉编译器使一个成员函数成为内联函数? 
[9.6]   有其它方法告诉编译器使成员函数成为内联吗? 
[9.7]   内联函数保证执行的更好吗?   


-------------------------------------------------------------------------------- 


[9.1]   内联函数是什么? 
内联函数是代码被插入到调用者代码串处的函数。如同   #define   宏,内联函数通过避免调用 
开销来提高执行效率,尤其是它能够通过调用(“过程集成”)被编译器优化。 

-------------------------------------------------------------------------------- 


[9.2]   内联函数是如何在安全和速度上取得折衷? 

在   c   中,你可以通过在结构中设置一个   void*   来得到“封装的结构”,在这种情况下,指向 
实际数据的   void*   指针对于结构的用户来说是未知的。因此结构的用户不知道如何解释void*   
指针所指内容,但是存取函数可以将   void*   转换成被隐藏的类型。这是封装的一种形式。 

不幸的是这样做丧失了类型安全,并且也将繁琐的对结构中的每个域的访问强加于函数调用。 
(如果你允许直接存取结构的域,那么对任何能直接存取的人来说,了解如何解释   void*   指针 
所指内容就是必要的了;这样将使改变底层数据结构变的困难) 

虽然函数调用开销是很小的,但它会被累积。c++类允许函数调用以内联展开。这样让你在得到 
封装的安全性时,同时得到直接存取的速度。此外,内联函数的参数类型由编译器检查,这是 
对   c   的   #define   宏的一个改进。 

-------------------------------------------------------------------------------- 


[9.3]   为什么我应该用内联函数?而不是原来清晰的   #define   宏? 
因为   #define   宏是有害的。 

和   #define   宏不同的是,内联函数总是对参数只精确地进行一次求值,从而避免了声名狼 
藉的宏错误。换句话说,调用内联函数和调用正规函数是等价的,差别仅仅是更快: 

        //   返回   i   的绝对值的宏 
        #define   unsafe(i)                             (   (i)   > =   0   ?   (i)   :   -(i)   ) 
        
        //   返回   i   的绝对值的内联函数 
        inline 
        int   safe(int   i) 
        { 
            return   i   > =   0   ?   i   :   -i; 
        } 
        
        int   f(); 
        
        void   usercode(int   x) 
        { 
            int   ans; 
        
            ans   =   unsafe(x++);       //   错误!x   被增加两次 
            ans   =   unsafe(f());       //   危险!f()被调用两次 
        
            ans   =   safe(x++);           //   正确!   x   被增加一次 
            ans   =   safe(f());           //   正确!   f()   被调用一次 
        }   

和宏不同的,还有内联函数的参数类型被检查,并且被正确地进行必要的转换。 

宏有害你的健康;万不得已不要用。 

-------------------------------------------------------------------------------- 


[9.4]   如何告诉编译器使非成员函数成为内联函数? 
声明内联函数看上去和普通函数非常相似: 

        void   f(int   i,   char   c);   

当你定义一个内联函数时,在函数定义前加上   inline   关键字,并且将定义放入头文件: 

        inline 
        void   f(int   i,   char   c) 
        { 
            //   ... 
        }   

注意:将函数的定义({...}之间的部分)放在头文件中是强制的,除非该函数仅仅被单 
个   .cpp   文件使用。尤其是,如果你将内联函数的定义放在   .cpp   文件中并且在其他   .cpp 
文件中调用它,连接器将给出“unresolved   external”错误。 

-------------------------------------------------------------------------------- 


[9.5]   如何告诉编译器使一个成员函数成为内联函数? 
声明内联成员函数看上去和普通函数非常类似: 

        class   fred   { 
        public: 
            void   f(int   i,   char   c); 
        };   

但是当你定义内联成员函数时,在成员函数定义前加上   inline   关键字,并且将定义放入 
头文件中。 

        inline 
        void   fred::f(int   i,   char   c) 
        { 
            //   ... 
        }   

通常将函数的定义({...}之间的部分)放在头文件中是强制的。如果你将内联函数的定义 
放在   .cpp   文件中并且在其他   .cpp   文件中调用它,连接器将给出“unresolved   external” 
错误。 

-------------------------------------------------------------------------------- 


[9.6]   有其它方法告诉编译器使成员函数成为内联吗? 
有:在类体内定义成员函数: 

        class   fred   { 
        public: 
            void   f(int   i,   char   c) 
                { 
                    //   ... 
                } 
        };   

尽管这对于写类的人来说很容易,但由于它将类是“什么”(what)和类“如何”(how)工作混 
在一起,给阅读的人带来了困难。我们通常更愿意在类体外使用   inline   关键字定义成员函数 
来避免这种混合。这种感觉所基于的认识是:在一个面向重用的世界中,使用你的类的人有很 
多,而建造它的人只有一个(你自己);因此你做任何事都应该照顾多数而不是少数。 

-------------------------------------------------------------------------------- 


[9.7]   内联函数保证执行的更好吗? 
不。 

小心过度使用内联函数可能导致代码膨胀。在页面调度环境中,它可能会给执行带来负面影响。 

-------------------------------------------------------------------------------- 
revised   sep   8,   1997