http://blog.csdn.net/xdrt81y/article/details/24333335

今天在做一个趋势笔试题的时候,才让我有了系统把const关键字好好总结一下的冲动,因为这个关键词大大小小好多地方都出现过,出现频率非常高,而每次只是简短的把答案看了一下,没有真正将其整个用法弄透,马上要找工作了,为避免悲剧再次发生,不得不引起我的重视,这才有了这篇博文。

    首先,一看到const关键字,我们的第一反应就是定义常量。的确,这没有错,const就是constant的缩写嘛,但是事实上他的用法远不止这些。接下来我们一一来讲解。
    在C程序中,const的用法主要有定义常量、修饰函数参数和修饰函数返回值。而在C++程序中,它除了上述功能外,还可以修饰函数的定义体,定义类中某个成员函数为恒态函数,即不改变类中的数据成员。对于定义常量的用法,这里就不多说了,重点看一下修饰函数参数、修饰函数返回值以及修饰函数的定义体。
    0)修饰变量或指针
int ii=0; 
const int i=0;           //i是常量,i的值不会被修改 
 
const int *p1i=&i;        //指针p1i所指内容是常量,可以不初始化 
int const* p11i = &i; //同上,const在*号左边,作用是一样的。
 
int  * const p2i=ⅈ    //指针p2i是常量,所指内容可修改 
 
const int * const p3i=&i; //指针p3i是常量,所指内容也是常量 
 
p1i=ⅈ                 //合法 
 
*p2i=100;               //合法
    1)修饰函数参数
    首先如果该参数用于输出,那么无论是采用指针传递还是引用传递,都不能加const修饰。所以const只能用于修饰输入参数。这里又分三种情况:输入参数采用值传递还是指针传递还是引用传递。
    (1)如果采用值传递,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不需要加const 修饰。
     例如,对于函数void Func1(int x),写成void Func1(const int x)一点意义也没有。同理,对于void Func2(A a)也不需要写成void Func2(const A a),其中A为用户自定义的对象类型。
    (2)如果采用指针传递,那么加const可以防止函数体内部对该参数进行改变,起到保护作用。
     例如,假设StringCopy函数定义为:void StringCopy(char *strDest, const char *strSrc),那么,如果函数体试图改变strSrc的内容,编译器将报错。
    (3)如果采用引用传递,
     首先我们来说一下,为什么要引入引用传递这种方法。原因是:对于非内部数据类型的参数而言,象void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为void Func(A& a)。这样一来,根据引用传递的定义,只是借用了参数的别名,不需要产生临时对象。
      但是,这样一来,当函数体中改变了参数a的值后,相应的传递的原始值也会相应改变。所以如果不希望改变原始参数,只需要在前面加上const修饰,这样一来,函数最终定义为void Func(const A& a)。同理,是否应将void Func(int x) 改写为void Func(const int &x),以便提高效率?完全没有必要,因为内部数据类型的参数不存在构造、析构的过程,而复制也非常快,“值传递”和“引用传递”的效率几乎相当。
     总结一下const作为函数输入参数的用法:
     (1)对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将void Func(A a) 改为void Func(const A &a)。
         (2)对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为void Func(const int &x)。
 
      2)修饰函数的返回值
      根据上面的思路,这里也分三种情况,即值传递、指针传递、引用传递。
      (1)如果函数返回值采用“值传递”方式,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。
     例如,不要把函数int GetInt(void) 写成const int GetInt(void)。同理不要把函数A GetA(void) 写成const A GetA(void),其中A 为用户自定义的数据类型。
    (2)如果函数返回值采用“指针传递”方式,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
     例如,定义函数为:const char *GetString(void),那么char *str = GetString()将会出现编译错误。应该写成const char *str = GetString()。
    (3)如果函数返回值是采用“引用传递”方式,它的意义在于能提供啊效率,而这种方式使用场合并不多。这个时候,一定要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回“别名”就可以了,否则程序会出错。
     例如,对于类的重载赋值函数A & operate = (const A &other),如果不加cons修饰,则定义A a, b, c;(a = b) = c,程序合法,但是如果加上const修饰,即const A & operate = (const A &other),则程序会报错。
 
       3)修饰函数的定义体。
       定义const函数,只需要将const关键字放在函数声明的尾部。任何不会修改类的数据成员的函数都应该声明为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_data[100];
};
int Stack::GetCount(void) const
{
  ++ m_num; // 编译错误,企图修改数据成员m_num
  Pop(); // 编译错误,企图调用非const 函数
  return m_num;
}
 
    到这里,const关键字的讲解就结束了。以下是几点使用const的几点规则。
    1) const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数。
    2) const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的。
    3) const成员函数不可以修改对象的数据,不管对象是否具有const性质.它在编译时,以是否修改成员数据为依据,进行检查。
    4) 然而加上mutable修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的const成员函数是可以修改它的。

C/C++中const关键字的更多相关文章

  1. C++中const关键字的使用总结

    C++中使用const关键字来修饰常量,下面从两个方面总结:变量和成员函数. 变量:const可以修饰普通变量.指针(数组)和结构体. 1.const修饰普通变量是最简单的情形.这样的用法多为在程序中 ...

  2. (转) C/C++中const关键字详解

    文章转自  http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 为什么使用const?采用符号常量写出的代码更容易维 ...

  3. C/C++中const关键字的用法及其与宏定义的比较

    1.const关键字的性质 简单来说:const关键字修饰的变量具有常属性. 即它所修饰的变量不能被修改. 2.修饰局部变量 ; ; 这两种写法是等价的,都是表示变量的值不能被改变,需要注意的是,用c ...

  4. C/C++中const关键字的用法及其与宏常量的比较

    1.const关键字的性质 简单来说:const关键字修饰的变量具有常属性. 即它所修饰的变量不能被修改. 2.修饰局部变量 ; ; 这两种写法是等价的,都是表示变量的值不能被改变,需要注意的是,用c ...

  5. C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!

    之前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点.知识用时方恨少,这一段时间正好各种笔试题,其中关于const的用法也是层出不穷,所以疲于在书本上各种翻,这里汇总一下,加深自 ...

  6. C++中const关键字详解

    1.什么是const? const意味着是常量类型,被const修饰的变量或对象是不能被修改和更新的,当然在某些情况下,我们可以偷梁换柱的改变它. 2.为什么要引入const? 最初的目的是为了取代预 ...

  7. C++中const关键字用法

    为什么使用const?采用符号常量写出的代码更容易维护:指针常常是边读边移动,而不是边写边移动:许多函数参数是只读不写的.const最常见用途是作为数组的界和switch分情况标号(也可以用枚举符代替 ...

  8. C++中const关键字 理解

    const:符号常量  使用符号常量写出的代码更容易维护:指针是边读边移动,而不是边写边移动,许多函数参数是只读不写的. const最常见用途是作为数组的界和switch分情况标号(也可以用枚举符代替 ...

  9. C++中const关键字用法总结

    看完了c++ primer的基础篇,对const还是有点陌生,在这里小小地总结一下吧. 1) const与变量 在变量的定义前加上 const 修饰符即可完成const对象的创建. const int ...

随机推荐

  1. 关于NOIP2018初赛

    题面 这次PJ初赛有点傻了,可能是因为兴华水土不服吧(在这荒度了六年级的光阴). 选择题 DDDBBAAAABABBBB 第四题 当时懵了,我啥也不知道,于是就开始蒙 A.LAN B.WAN C.MA ...

  2. 如何将文本编辑器嵌入框架--以Umeditor&CodeIgniter框架为例

    转:http://blog.csdn.net/u013332865/article/details/52066211 最近接到一个给某私立贵族(小,初,高 12年只是学费近200W)学校做一个网站,时 ...

  3. T-SQL语句3

    一.删除表 1.drop table语句 drop table database_name,schema_name,table_name 2.删除数据表 drop table dbo.t_delete ...

  4. spring mvc activemq

    http://websystique.com/spring/spring-4-jms-activemq-example-with-jmslistener-enablejms/

  5. Vue.js开始第一个项目

    前端架构之路:使用Vue.js开始第一个项目   Vue.js做为目前前端最热门的库之一,为快速构建并开发前端项目多了一种思维模式.本文通过一个简单的实例开始上手Vue.js开发. 一.技术准备 使用 ...

  6. 【LOJ】#6434. 「PKUSC2018」主斗地

    题解 什么,我这题竟然快到了LOJ rk1???? 搜起来有点麻烦,不过感觉还是比斗地主好下手(至今没敢写斗地主 首先是暴力搜牌型,最多\(3^{16}\)(什么判解还要复杂度怂成一团)的样子?? 然 ...

  7. 给虚拟机下面的ubuntu系统增加硬盘存储空间

    给虚拟机下面的ubuntu系统增加硬盘存储空间   由于ubuntu系统是安装在vsphere上面的,所以可能会和vmware上面的有一点区别,打开exsi系统的配置页面,如下图所示. 选择添加存储器 ...

  8. js变量和函数声明的提升(转)

    原文:http://zha-zi.iteye.com/blog/2037026 下面的程序是什么结果? var foo = 1; function bar() { if (!foo) { var fo ...

  9. 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 前一篇文章 ...

  10. Spring重复扫描导致事务失败的解决方案及深入分析

    问题及日志使用Spring和mybatis,然后配置事务,出现SqlSession was not registered for synchronization because synchroniza ...