关键词const详解——整理

上传人:子 文档编号:43184689 上传时间:2018-06-04 格式:DOC 页数:15 大小:86KB
返回 下载 相关 举报
关键词const详解——整理_第1页
第1页 / 共15页
关键词const详解——整理_第2页
第2页 / 共15页
关键词const详解——整理_第3页
第3页 / 共15页
关键词const详解——整理_第4页
第4页 / 共15页
关键词const详解——整理_第5页
第5页 / 共15页
点击查看更多>>
资源描述

《关键词const详解——整理》由会员分享,可在线阅读,更多相关《关键词const详解——整理(15页珍藏版)》请在金锄头文库上搜索。

1、看到 const 关键字,C+程序员首先想到的可能是 const 常量。这可不是良 好的条件反射。如果只知道用 const 定义常量,那么相当于把火药仅用于制作 鞭炮。const 更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义 体。 const 是 constant 的缩写, “恒定不变”的意思。被 const 修饰的东西都受到 强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多 C+程序设 计书籍建议:“Use const whenever you need”。1.用用 const 修饰函数的参数修饰函数的参数 如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递

2、”还 是“引用传递”,都不能加 const 修饰,否则该参数将失去输出功能。const 只能 修饰输入参数: 如果输入参数采用如果输入参数采用“指针传递指针传递”,那么加,那么加 const 修饰可以防止意外地改动该修饰可以防止意外地改动该 指针,起到保护作用。指针,起到保护作用。 例如 StringCopy 函数: void StringCopy(char *strDestination, const char *strSource); 其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动

3、如果函数体内的语句试图改动 strSource 的内容,编译器将指出的内容,编译器将指出 错误。错误。 如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参 数,该输入参数本来就无需保护,所以不要加 const 修饰。 例如不要将函数 void Func1(int x) 写成 void Func1(const int x)。同理不要将 函数 void Func2(A a) 写成 void Func2(const A a)。其中 A 为用户自定义的数据 类型。 对于非内部数据类型的参数而言,象 void Func(A a) 这样声明的函数注定 效率比较底。因为函数体内将产生 A 类

4、型的临时对象用于复制参数 a,而临时 对象的构造、复制、析构过程都将消耗时间。 为了提高效率,可以将函数声明改为为了提高效率,可以将函数声明改为 void Func(A 如下语句将出现编译错误: char *str = GetString(); 正确的用法是 const char *str = GetString(); 如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存 储单元中,加 const 修饰没有任何价值。 例如不要把函数 int GetInt(void) 写成 const int GetInt(void)。 同理不要把函数 A GetA(void) 写成 cons

5、t A GetA(void),其中 A 为用户自定义 的数据类型。 如果返回值不是内部数据类型,将函数 A GetA(void) 改写为 const A / 赋值函数 ; A a, b, c; / a, b, c 为 A 的对象a = b = c; / 正常的链式赋值 (a = b) = c; / 不正常的链式赋值,但合法 如果将赋值函数的返回值加 const 修饰,那么该返回值的内容不允许被改动。 上例中,语句 a = b = c 仍然正确,但是语句 (a = b) = c 则是非法的。3. const 成员函数成员函数 任何不会修改数据成员数据成员(即函数中的变量即函数中的变量)的函数都应

6、该声明为 const 类型。如果 在编写 const 成员函数时,不慎修改了数据成员,或者调用了其它非 const 成 员函数,编译器将指出错误,这无疑会提高程序的健壮性。以下程序中,类 stack 的成员函数 GetCount 仅用于计数,从逻辑上讲 GetCount 应当为 const 函数。编译器将指出 GetCount 函数中的错误。 class Stack public: void Push(int elem); int Pop(void); int GetCount(void) const; / const 成员函数 private: int m_num; int m_data10

7、0; ; int Stack:GetCount(void) const + m_num; / 编译错误,企图修改数据成员 m_num Pop(); / 编译错误,企图调用非 const 函数 return m_num; const 成员函数的声明看起来怪怪的:const 关键字只能放在函数声明的尾部, 大概是因为其它地方都已经被占用了。 关于 Const 函数的几点规则:a. const 对象只能访问 const 成员函数,而非 const 对象可以访问任意的成员函数, 包括 const 成员函数. b. const 对象的成员是不可修改的,然而 const 对象通过指针维护的对象却是可以 修

8、改的. c. const 成员函数不可以修改对象的数据,不管对象是否具有 const 性质.它在编译 时,以是否修改成员数据为依据,进行检查. e. 然而加上 mutable 修饰符的数据成员,对于任何情况下通过任何手段都可修改, 自然此时的 const 成员函数是可以修改它的看到 const 关键字,很多程序员想到的可能是 const 常量,这可有点象踩到陷井上还不知 道自己危险了。读读以下文字会使你对 c+中的 const 有一个全面的认识。 const 是 C+中常用的类型修饰符,有某些微妙的应用场合,如果没有搞清本源,则 错误在所难免。本篇中将对 const 进行辨析。溯其本源,究其实

9、质,希望能对大家理解 const 有所帮助,根据思维的承接关系,分为如下几个部分进行阐述。C+中为什么会引入 constC+的提出者当初是基于什么样的目的引入(或者说保留)const 关键字呢?,这是一 个有趣又有益的话题,对理解 const 很有帮助。1 大家知道,C+有一个类型严格的编译系统,这使得 C+程序的错误在编译阶段 即可发现许多,从而使得出错率大为减少,因此,也成为了 C+与 C 相比,有着突出优点 的一个方面。2 C 中很常见的预处理指令 #define VariableName VariableValue 可以很方便地进行 值替代,这种值替代至少在三个方面优点突出:一是避免了

10、意义模糊的数字出现,使得程序语义流畅清晰,如下例:#define USER_NUM_MAX 107 这样就避免了直接使用 107 带来的困惑。二是可以很方便地进行参数的调整与修改,如上例,当人数由 107 变为 201 时,进改 动此处即可,三是提高了程序的执行效率,由于使用了预编译器进行值替代,并不需要为这些常量 分配存储空间,所以执行的效率较高。鉴于以上的优点,这种预定义指令的使用在程序中随处可见。3 说到这里,大家可能会迷惑上述的 1 点、2 点与 const 有什么关系呢?,好,请接着 向下看来:预处理语句虽然有以上的许多优点,但它有个比较致命的缺点,即,预处理语句仅仅 只是简单值替代

11、,缺乏类型的检测机制。这样预处理语句就不能享受 C+严格类型检查的 好处,从而可能成为引发一系列错误的隐患。4好了,第一阶段结论出来了:结论: Const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承 它的优点。现在它的形式变成了:Const DataType VariableName = VariableValue ;为什么 const 能很好地取代预定义语句?const 到底有什么大神通,使它可以振臂一挥取代预定义语句呢?1 首先,以 const 修饰的常量值,具有不可变性,这是它能取代预定义语句的基础。2 第二,很明显,它也同样可以避免意义模糊的数字出现,同样可以很方便

12、地进行 参数的调整和修改。3 第三,C+的编译器通常不为普通 const 常量分配存储空间,而是将它们保存在符 号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率 也很高,同时,这也是它取代预定义语句的重要基础。这里,我要提一下,为什么说这一点是也是它能取代预定义语句的基础,这是因为, 编译器不会去读存储的内容,如果编译器为 const 分配了存储空间,它就不能够成为一个编译期间的常量了。4 最后,const 定义也像一个普通的变量定义一样,它会由编译器对它进行类型的检测, 消除了预定义语句的隐患。const 使用情况分类详析1.const 用于指针的两种情况分析:

13、int const *a; /a/可变,*a 不可变int *const a; /a 不可变,*a 可变分析:const 是一个左结合的类型修饰符,它与其左侧的类型修饰符合为一个类型修饰符,所以,int const 限定 *a,不限定 a。int *const 限定 a,不限定*a。2.const 限定函数的传递值参数:void fun(const int var);分析:上述写法限定参数在函数体中不可被改变。由值传递的特点可知,var 在函数体 中的改变不会影响到函数外部。所以,此限定与函数的使用者无关,仅与函数的编写者有 关。结论:最好在函数的内部进行限定,对外部调用者屏蔽,以免引起困惑。

14、如可改写如 下:void fun(int var)const int varalias .3.const 限定函数的值型返回值:const int fun1();const myclass fun2();分析:上述写法限定函数的返回值不可被更新,当函数返回内部的类型时(如 fun1) , 已经是一个数值,当然不可被赋值更新,所以,此时 const 无意义,最好去掉,以免困惑。当函数返回自定义的类型时(如 fun2) ,这个类型仍然包含可以被赋值的变量成员,所以, 此时有意义。传递与返回地址: 此种情况最为常见,由地址变量的特点可知,适当使用 const,意义昭 然。5. const 限定类的成

15、员函数:class classname public:int fun() const;.注意:采用此种 const 后置的形式是一种规定,亦为了不引起混淆。在此函数的声明 中和定义中均要使用 const,因为 const 已经成为类型信息的一部分。获得能力:可以操作常量对象。失去能力:不能修改类的数据成员,不能在函数中调用其他不是 const 的函数。1.1.1. 定义普通常量 使用#define 来定义常量也是常用方法,但 const 也可以用来定义常量,在Effective C+中 建议使用 const 代替#define 来定义常量,因为 const 定义的常量具有类型信息,而宏没有,

16、所以使用 const 定义的常量在进行赋 1.1.1. 定义普通常量 使用#define 来定义常量也是常用方法,但 const 也可以用来定义常量,在Effective C+中 建议使用 const 代替#define 来定义常量,因为 const 定义的常量具有类型信息,而宏没有, 所以使用 const 定义的常量在进行赋值操作时编译器会进行更严格的类型检查,是类型安 全的。const double PI = 3.1414926;const int POOL_SIZE = 20;定义常量有三种方法:宏、const、enum,其中宏应该尽量避免,而 const 与 enum 也各有 优缺点,最大的区别就是 enum 只能用于定义整数,而不能定义浮点数;而对于定义逻辑 关系较近的一组整数时比较适合使用 enum,也可以考虑使用类代替 enum(参见?)。常量必须在定义时进行初始化,之后便不能再赋值。说它不能被赋值并不是说常量

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号