请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

猿媛之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 3744|回复: 0

C/C++ const有哪些作用

[复制链接]

44

主题

48

帖子

198

积分

注册会员

Rank: 2

积分
198
发表于 2016-1-17 22:50:39 | 显示全部楼层 |阅读模式
    常类型也称为const类型,是指使用类型修饰符const说明的类型。constCC++中常见的关键字,在C语言中,它主要用于定义变量为常类型以及修饰函数参数与返回值,而在C++中还可以修饰函数的定义,定义类的成员函数。常类型的变量或对象的值是不能被更新的。
    一般而言,const有以下几个方面的作用:
    (1)定义const常量,具有不可变性。例如:
  1. const int MAX=100;
  2. int Array[MAX];
复制代码
    (2)进行类型检查,使编译器对处理内容有更多的了解,消除了一些隐患。例如:voidf(const int i) { ...} 编译器就会知道i是一个常量,不允许修改。
    (3)避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。同宏定义一样,可以做到不变则已,一变都变。如(1)中,如果想修改MAX的内容,只需要定义const int MAX =期望值即可。
    (4)保护被修饰的东西,防止被意外的修改,增强了程序的健壮性。在上例中,如果在函数体内修改了变量i的值,那么编译器就会报错。例如:
  1. void f(const int i)
  2. {
  3.   i=10;
  4. }
复制代码
    上述代码对i赋值会导致编译错误。
    (5)为函数重载提供参考。
  1. class A
  2. {
  3.     void f(int i) {...}                               //定义一个函数
  4.     void f(int i) const {...}      //上一个函数的重载
  5. }
复制代码
    (6)节省空间,避免不必要的内存分配。例如
  1. #define PI 3.14159                               //该宏用来定义常量
  2. const doulbe Pi=3.14159;     //此时并未将Pi放入只读存储器中
  3. double i=Pi;                                          //此时为Pi分配内存,以后不再分配
  4. double I=PI;                                         //编译期间进行宏替换,分配内存
  5. double j=Pi;                                          //没有内存分配
  6. double J=PI;                                         //再次进行宏替换,又一次分配内存
复制代码
    const定义常量从汇编的角度来看只是给出了对应的内存地址而不是像#define一样给出的是立即数所以const定义的常量在程序运行过程中只有一份复制品#define定义的常量在内存中有若干个复制品。
    7提高了程序的效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
引申1:什么情况下需要使用const关键字?
    1)修饰一般常量。一般常量是指简单类型的常量。这种常量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后。 例如: int constx=2 const int x=2
    2)修饰常数组。定义或说明一个常数组可以采用如下格式:
  1. int const a[8]={1, 2, 3, 4, 5, 6, 7, 8};
  2. const int a[8]={1, 2, 3, 4, 5, 6, 7, 8};
复制代码
    3)修饰常对象。常对象是指对象常量,定义格式如下:
  1. class A;
  2. const A a;
  3. A const a;
复制代码
    定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面。
    4)修饰常指针。
  1. const int *A; //const修饰指向的对象,A可变,A指向的对象不可变
  2. int const *A; //const修饰指向的对象,A可变,A指向的对象不可变
  3. int *const A; //const修饰指针A,A不可变,A指向的对象可变
  4. const int *const A;//指针A和A指向的对象都不可变
复制代码
    5)修饰常引用。使用const修饰符也可以说明引用,被说明的引用为常引用,该引用所引用的对象不能被更新。其定义格式如下:
  1. const double & v;
复制代码
    6)修饰函数的常参数。const修饰符也可以修饰函数的传递参数,格式如下:
  1. void Fun(const int Var);
复制代码
    告诉编译器var在函数体中的无法改变,从而防止了使用者一些无意的或错误的修改。
    7)修饰函数的返回值。const修饰符也可以修饰函数的返回值,返回值不可被改变,格式如下:
  1. const int Fun1( );
  2. const MyClass Fun2( );
复制代码
    8)修饰类的成员函数。const修饰符也可以修饰类的成员函数,格式如下:
  1. class ClassName
  2. {
  3.     public:
  4.     int Fun( ) const;
  5. };
复制代码
    这样,在调用函数Fun( )时就不能修改类或对象的属性。
    9)在另一连接文件中引用const常量。使用方式有:
  1. extern const int i;
  2. extern const int j=10;
复制代码
    第一种用法是正确的,而第二种用法是错误的,常量不可以被再次赋值。另外,还要注意,常量必须初始化,如constint i=5
    引申2:什么是常引用
    常引用也称为const引用。之所以引入常引用,是为了避免在使用变量的引用时,在毫不知情的情况下改变了变量的值,从而引起程序错误。常引用主要用于定义一个普通变量的只读属性的别名,作为函数的传入形参,避免实参在调用函数中被意外地改变。
const引用的意思是指向const对象的引用,非const引用表示指向非const类型的引用。如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:
const 类型标识符 & 引用名 = 目标变量名;
常引用的主要用途如下:
    1)用做普通变量的只读属性的别名。通常这个别名只能获得这个变量的值,而不能改变这个变量的值。
    2)用于函数的形参。常引用做形参,可以确保在函数内不会改变实参的值,所以参数传递时尽量使用常引用类型。
如果是对一个常量进行引用,则编译器首先建立一个临时变量,然后将该变量的值置入临时变量中,对该引用的操作就是对该临时变量的操作,对常量的引用可以用其他任何引用来初始化,但不能改变。
关于引用的初始化,一般需要注意以下问题:当初始化值是一个左值(可以取得地址)时,没有任何问题;而当初始化值不是一个左值时,则只能对一个常引用赋值,而且这个赋值是有一个过程的,首先将值隐式转换到类型T,然后将这个转换结果存放在一个临时对象里,最后用这个临时对象来初始化这个引用变量。例如如下两种使用方式:
  1. (1)double& dr = 1;
  2. (2)const double& cdr = 1;
复制代码
    第(1种方法错误,初始化值不是左值,而第(2)种方法正确,其对应的执行过程如下:
  1. double temp = double(1);
  2. const double& cdr = temp;
复制代码
    如果对第(1)种使用方法进行相应的改造,也可以变为合法,例如
  1. const int ival = 1024 ;
  2. (1)const int &refVal=ival ;
  3. (2)int &ref2=ival ;
复制代码
    在上例中1种方法的引用是合法的而第2种方法的引用是非法的。上例中,可以读取refVal的值但是不能修改它,因为refVal的类型是const任何对refVal的赋值都是不合法的(const引用是只读的,常量即不能作为左值的量,定义式中赋初值除外)。同时,const引用可以初始化为不同类型的对象或者初始化为右值,如字面值常量,而非const引用只能绑定到与该引用同类型的对象。例如,下述const引用都是合法的。
  1. int i = 42;
  2. const int &r = 42;
  3. const int &r2 = r + i;
复制代码
    在使用const引用进行函数调用的时候,需要注意一个问题,例如如下函数声明:
  1. void bar(string & s);
复制代码
    那么下面的表达式将是非法的:
  1. bar("hello world");
复制代码
    程序示例如下所示:
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. void bar(string& s)
  5. {
  6.              cout<<s<<endl;
  7. }
  8. int main( )
  9. {
  10.              bar("hello world");
  11.              return 0;
  12. }
复制代码
    程序输出为
hello world
    原因在于“helloworld”串会产生一个临时对象,而在C++中,临时对象是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。引用型参数应该在能被定义为const 的情况下,尽量定义为const

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|猿媛之家    

GMT+8, 2020-2-28 13:02 , Processed in 0.255981 second(s), 28 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表