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)。

const与#define宏常量 , inline与#define的更多相关文章

  1. #define宏常量和const常量的区别

    C++ 语言可以用const 来定义常量,也可以用#define 来定义常量.但是前者比后者有更多的优点:(1) const 常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查.而 ...

  2. Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define

    尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...

  3. 枚举与#define 宏的区别

    1),#define 宏常量是在预编译阶段进行简单替换.枚举常量则是在编译的时候确定其值.2),一般在编译器里,可以调试枚举常量,但是不能调试宏常量.3),枚举可以一次定义大量相关的常量,而#defi ...

  4. 如何正确使用const(常量),define(宏)

    前言 在开发中,也许我们会经常使用到宏定义,或者用const修饰一些数据类型,经常有开发者不知道怎么正确使用,导致项目中乱用宏定义与const修饰符.本篇主要介绍在开发中怎么正确使用const与def ...

  5. iOS define 宏定义 和 const定义常量区别

    const   const 是c++中的修饰符.  c++中常用来定义常量,修饰左值. #define 宏定义语句, 在预处理阶段直接做文本替换,不做类型检查. 它们之间的最大区别: 1.  对于co ...

  6. iOS学习——iOS 宏(define)与常量(const)的正确使用

    概述 在iOS开发中,经常用到宏定义,或用const修饰一些数据类型,经常有开发者不知怎么正确使用,导致项目中乱用宏与const修饰.你能区分下面的吗?知道什么时候用吗? #define HSCode ...

  7. const常量与define宏定义的区别(转)

    #define RADIUS 100; const  float   RADIUS = 100; (1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行阶段使用. ( ...

  8. EC笔记,第一部分:2.尽量以const,enum,inline代替#define

    02.尽量以const,enum,inline代替#define 原因:编译前的预处理会替换宏,所以调试的时候找不到错误 1.const 尽量用const替代常量宏定义 两种特殊情况: (1).常量指 ...

  9. Effective C++ 之 Item 2:尽量以 const, enum, inline 替换 #define

    Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 2. 尽量以 const, enum, inline 替换 #d ...

随机推荐

  1. 设置完在Canvas的位置后,控件HitTest不响应的问题

    have a Canvas with a couple of elements on it like Line, Path and Text Box. In the MouseOver event o ...

  2. 【Linux程序设计】之环境系统函数综合实验

    这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的.贴出来纯粹是聊胜于无. 实验题目:Linux环境下系统函数综合实验 实验目的:熟悉并掌握Linux环境下数学函 ...

  3. BestCoder Round #78 (div.2)

    因为rating不够QAQ就报了Div2.. [CA Loves Stick] CA喜欢玩木棍. 有一天他获得了四根木棍,他想知道用这些木棍能不能拼成一个四边形. Sample Input 2 1 1 ...

  4. hiho 光棍节

    描述 尽管付出了种种努力,jzp还是得过光棍节. jzp非常不爽,但也无能为力,只能够哀叹起来他的命运.他想到了一位长者的人生经验:“人的一生,不光要靠自我奋斗,也要考虑历史的进程”. 他终于明白自己 ...

  5. cJSON应用举例

    //在网上查了不少cJSON,结果只找到c语言字符串转换到JSON的实例,想转回来结果没有实例.自己琢磨了一个下午才敢下手.下面把转来转去的代码贴上. //百度网盘的 CJSON 实例源码 地址 ht ...

  6. 小问题,小细节要注意(string类型转换为bool类型)

    一个表中的推荐字段是bit类型的,添加的时候推荐有两个值,如<asp:RadioButtonList ID="RadioButtonList1" runat="se ...

  7. RN组件之ListView

    /** * Created by DaGuo on 2016/4/7. */ 'use strict' import React,{ Component, View, Text, ListView, ...

  8. 用 Freemarker 生成 word 文档(包含图片)

    1. 用word写一个需要导出的word模板,然后存为xml格式. 2. 将xml中需要动态修改内容的地方,换成freemarker的标识符,例如: <w:p wsp:rsidR="0 ...

  9. iOS移动开发周报-第21期

    iOS移动开发周报-第21期 [摘要]:本期iOS移动开发周报带来如下内容:苹果iCloud中国数据转存中国电信,Swift Operators,100 个 Swift 必备 tips,FLEXLoa ...

  10. 【C语言】09-字符串

    一.字符串简介 * 在Java中,一个字符串可以用String类型来存储 String s = "MJ"; C语言中没有String这种类型.其实字符串就是字符序列,由多个字符组成 ...