#define RADIUS 100;

const  float   RADIUS = 100;

(1) 编译器处理方式不同

  define宏是在预处理阶段展开。

  const常量是编译运行阶段使用。

(2) 类型和安全检查不同

  define宏没有类型,不做任何类型检查,仅仅是展开。

  const常量有具体的类型,在编译阶段会执行类型检查。

(3) 存储方式不同

  define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。(宏定义不分配内存,变量定义分配内存。)

  const常量会在内存中分配(可以是堆中也可以是栈中)。

(4)const  可以节省空间,避免不必要的内存分配。 例如:  
        #define PI 3.14159 //常量宏  
        const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 ......  
        double i=Pi; //此时为Pi分配内存,以后不再分配!  
        double I=PI; //编译期间进行宏替换,分配内存  
        double j=Pi; //没有内存分配  
        double J=PI; //再进行宏替换,又一次分配内存!  
        const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define定义的常量在内存中有若干个拷贝。 
(5) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

(6) 宏替换只作替换,不做计算,不做表达式求解;

宏预编译时就替换了,程序运行时,并不分配内存。

const 与 #define的比较

C++ 语言可以用const来定义常量,也可以用 #define来定义常量。但是前者比后者有更多的优点:

(1)   const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。

(2)   有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

【规则5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。

5.3常量定义规则

【规则5-3-1】需要对外公开的常量放在头文件中,不需要对外公开的常量放在定义文件的头部。为便于管理,可以把不同模块的常量集中存放在一个公共的头文件中。

【规则5-3-2】如果某一常量与其它常量密切相关,应在定义中包含这种关系,而不应给出一些孤立的值。

例如:

const  float   RADIUS = 100;

const  float   DIAMETER = RADIUS * 2;

5.4类中的常量

有时我们希望某些常量只在类中有效。由于#define定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用const修饰数据成员来实现。const数据成员的确是存在的,但其含义却不是我们所期望的。const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。

不能在类声明中初始化const数据成员。以下用法是错误的,因为类的对象未被创建时,编译器不知道SIZE的值是什么。

class A

{…

const int SIZE = 100; // 错误,企图在类声明中初始化const数据成员

int array[SIZE];       // 错误,未知的SIZE

};

const数据成员的初始化只能在类构造函数的初始化表中进行,例如

class A

{…

A(int size);       // 构造函数

const int SIZE ;

};

A::A(int size) : SIZE(size) // 构造函数的初始化表

{

}

A  a(100);  // 对象 a 的SIZE值为100

A  b(200);  // 对象 b 的SIZE值为200

怎样才能建立在整个类中都恒定的常量呢?别指望const数据成员了,应该用类中的枚举常量来实现。例如

class A

{…

enum { SIZE1 = 100, SIZE2 = 200}; //枚举常量

int array1[SIZE1];

int array2[SIZE2];

};

枚举常量不会占用对象的存储空间,它们在编译时被全部求值。枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点数(如PI=3.14159)。sizeof(A) = 1200;其中枚举部长空间。

enum   EM { SIZE1 = 100, SIZE2 = 200}; //枚举常量   sizeof(EM) = 4;

const常量与define宏定义的区别(转)的更多相关文章

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

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

  2. 面试问题5:const 与 define 宏定义之间的区别

    问题描述:const 与 define 宏定义之间的区别 (1) 编译器处理方式不同     define宏是在预处理阶段展开:     const常量是编译运行阶段使用: (2) 类型和安全检查不同 ...

  3. const 常量与 define常量的区别

    c++中的常量可以使用const定义,也可以使用#define宏定义的方式:二者区别如下: - **区别** 1. const定义的常量有自己的数据类型,编译器可以对其进行严格的类型检查:但是defi ...

  4. inline-内联函数的优点以及与宏定义的区别

    inline函数的优点: C++ 语言的函数内联机制既具备宏代码的效率,又增加了安全性,而且可以自由操作类的数据成员.所以在C++ 程序中,应该用内联函数取代所有宏代码. inline函数与宏定义的区 ...

  5. define宏定义中的#,##,@#及\符号

    define宏定义中的#,##,@#及\符号 在#define中,标准只定义了#和##两种操作.#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串. 1.# (string ...

  6. C++中的内联函数和C中的宏定义的区别

    在C++中内联函数: 内联函数即是在函数的声明和和定义前面加上“inline”关键字,内联函数和常规函数一样,都是按照值来传递参数的,如果参数为表达式,如4.5+7.5,则函数将传递表达式的值(这里为 ...

  7. iOS 7:漫谈#define 宏定义(转)

    iOS :漫谈#define 宏定义 #define宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步 ...

  8. 在 C++ 程序中只使用 const 常量而不使用宏常量

    在 C++ 程序中只使用 const 常量而不使用宏常量,即 const 常量完 全取代宏常量. #include <iostream> /* run this program using ...

  9. define宏定义和const常变量区别

    1.define是宏定义,程序在预处理阶段将用define定义的内容进行了替换.因此程序运行时,常量表中并没有用define定义的常量,系统不为它分配内存.const定义的常量,在程序运行时在常量表中 ...

随机推荐

  1. 深入了解Redis(7)-缓存穿透,雪崩,击穿

    redis作为一个内存数据库,在生产环境中使用会遇到许多问题,特别是像电商系统用来存储热点数据,容易出现缓存穿透,雪崩,击穿等问题.所以实际运用中需要做好前期处理工作. 一.缓存雪崩 1.概念 缓存雪 ...

  2. 如何从0到1的构建一款Java数据生成器-第一章

    前提 某天晚上老夫在神游时,想起白天公司同事说起的问题,这老表抱怨使用mysql生成大批的随机测试数据太过麻烦,问大家有没有好的工具推荐,老夫对这种事情当然不关心,毕竟我也不知道. 秉承着不懂就要问, ...

  3. phpstorm 注解路由插件

    idea-php-annotation-plugin 设置 插件 搜索 安装 重启

  4. ansible用user/group模块管理受控机上的用户和组(ansible2.9.5)

    一,ansible的user/group模块的用途: ansible的user模块用来实现:生成用户.删除用户等用户的管理ansible的group模块用来实现:生成组.删除组等组的管理 说明:刘宏缔 ...

  5. JavaSE学习笔记03流程控制

    Java流程控制 1.顺序结构 java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句往下执行. 顺序结构是最简单的算法结构,它是任何一个算法都离不开的一种基本算法结构. 2. 选择结构 ...

  6. Linux命令之tab 键补全

    tab 键补全 tab 键可以实现命令及路径等补全,提高输入效率,避免出错 命令补全 用户给定的字符串只有一条惟一对应的命令,直接补全, 两次Tab会给出列表 内部命令: 外部命令:bash根据PAT ...

  7. 503. 下一个更大元素 II

    503. 下一个更大元素 II 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大 ...

  8. exe打包成安装文件(界面美观)

    前言 在开发windows桌面应用过程中,软件交付时,一般都是交付安装包. 安装文件的优点 显得更正规,安装界面也可展示软件特点介绍,可自动生成桌面图标等: 安装包体积要比软件小,方便下载. 探索之路 ...

  9. Yum 命令出现[Errno 256] No more mirrors to try错误的解决方式

    今天我在虚拟机上安装 NetCore 的 SDK 的时候,出现错误,执行命令:"yum install dotnet-sdk-3.1",最后安装失败,很多安装包没有找到镜像.解决方 ...

  10. CodeForces 916D Jamie and To-do List

    题意 你需要维护一个任务列表,有 \(q\) 次操作,每次操作形如以下四种: set a x:设置任务 \(a\) 的优先级为 \(x\),如果任务列表中没有 \(a\) 则加进来. remove a ...