const与#define宏常量 , inline与#define

1.预处理

  预处理器是在真正的编译开始之前由编译器调用的独立程序。预处理器可以删除注释、包含其他文件以及执行宏替代。

     预处理命令(宏定义#define..#undef、

                      文件包含#include、

                     条件编译#ifndef...(#else)...#endif   或者   #if...(#else)..#endif)

      不是C++语句(以“#”开头,末尾不包含分号),不能直接编译。

    宏的优缺点说明:

    1). 首先谈一下在C中使用这种形式宏定义的原因,C语言是一个效率很高的语言,这种宏定义在形式及使用上像一个函

            数,但它使用预处理器实现,没有参数压栈,代码生成等一系列的操作,因此,效率很高,这是它在C中被使用的一个

            主要原因。

     2). 这种宏定义在形式上类似于一个函数,但在使用它时,仅仅只是做预处理器符号表中简单替换,因此它不能进行

             参数有效性的检测也就不能享受C++编译器严格类型检查的好处,另外它的返回值也不能被强制转换为可转换的合适的

              类型,这样,它的使用就存在着一系列的隐患和局限性

     3). 在C++中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,就不

             可能使用这种宏定义来实现(因为无法将this指针放在合适的位置)。

2. inline

     inline 推出的目的:为了取代宏定义,它消除了宏定义的缺点,同时又很好地继承了宏定义的优点。

     inline的优点

     1). inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率很高。

     2). 类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,

            就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性

     3). inline 可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员

     注意:可以在声明函数和定义函数的时候同时写inline,也可以只在其中一处声明inline,效果相同,都能按内置函数处理。

    inline的局限性

      1). 使用内置函数可以节省运行时间,但却增加了目标程序的长度。因此一般只将规模很小而使用频繁的函数声明为内置函数

      2). 内置函数不包含复杂的控制语句,如循环语句和switch语句

      3). 对函数inline声明,只是程序设计者对编译系统提出的一个建议,编译系统会根据具体情况决定是否这样做。

     慎用内联:

       内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

    以下情况不宜使用内联:         

    (1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。    

    (2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。       

    (3)类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些

           行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。

      inline与宏的区别总结:

       1). 内联函数和宏的区别在于,是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,

          只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。

       2). 内联函数与带参数宏定义的另一个区别是,内联函数的参数类型返回值类型在声明中都有明确的指定;而带参数宏

           定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患。

3. const 推出的初始目的:为了取代预编译指令,消除它的缺点,同时继承它的优点。

     const的作用

     (1)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。可以保护被修饰的东西,防止意外的修改,增强程序的健壮性
   (2)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改同宏定义一样,可以做到不变则已,一变都变
   (3) 可以节省空间,避免不必要的内存分配。 例如: 
    #define PA 3.14159 //常量宏 
    const double Pi=3.14159; //此时并未将Pi放入RAM中 ...... 
    double i=Pi; //此时为Pi分配内存,以后不再分配 
    double I=PA; //编译期间进行宏替换,分配内存 
    double j=Pi; //没有内存分配 
    double J=PA; //再进行宏替换,又一次分配内存! 
        const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,

             所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝 
  (4) 提高了效率。 
        编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量没有了存储与读内存的操作,使得它的效率也很高

    const与宏常量的区别:

       1). const常量有数据类型,而宏常量没有数据类型 编译器可以对前者进行类型安全检查,而对后者只能进行字符替换,没有安全检查,

           并且在字符替换时可能会产生意料不到的错误。

       2). 编译器对二者的调试 有些集成化的调试工具可以对const常量进行调试, 在 c++程序中只使用const常量而不使用宏常量,

             即const常量完全取代宏常量。

通过上面的分析,总结为一句话:尽量用编译器(const、inline),而不用预处理(#define)。

 

posted @ 2014-03-30 13:14  Xylophone  Views(872)  Comments(0Edit  收藏  举报