const用法

const用法: 
一、总述
修饰符const用来限定变量只能被读取,不能被修改。当定义一个常量(const)时,必须赋一个值给它。
    C++中的const默认为内部连接,也就是说,const仅在const被定义过的文件里才是可见的,而在连接时不能被其他编译单元看到。
因此,可以把const的定义放在一个头文件中,让多个cpp文件包含该头文件,而不会出现重复定义。也可以在一个文件中定义
常量const int i=10,在另一个cpp文件中使用extern int i连接该常量。
    C++编译器通常并不为const分配存储空间,相反它把这个定义保存在它的符号表里。但这不是绝对的,如取一个const变量的地址,就要进行存储空间分配。
    定义或说明一个常数组可采用如下格式:int const a[5]={1, 2, 3, 4, 5};或者const int a[5]={1, 2, 3, 4, 5}。
常量与数组的组合有什么特殊吗?我们给出下面的代码
const int size[3]={10,20,50};
int array[size[2]];


有什么问题吗?对了,编译通不过!为什么呢?
    const可以用于集合,但编译器不能把一个集合存放在它的符号表里,所以必须分配内存。在这种情况下,const意味着“不能改变的一块存储”。然而,
其值在编译时不能被使用,因为编译器在编译时不需要知道存储的内容。自然,作为数组的大小就不行了。
    下面给出几种常量初始化表达式:
int a=10;
const int b=a;//OK,可以将变通变量赋值给常量
const int * c=&a; //OK,可以将变通变量的地址赋值给常量指针(指针指向一个常量)
int * const d=&a; //OK,可以将变通变量的地址赋值给指针常量(指针本身是常量)
const int * const e=&a; // OK,可以将变通变量的地址赋值给指向常量的指针常量
const int & f=a; //OK,可以将变通变量赋值给常量引用
int g=b;//OK
int * h=c;//error,可通过h修改c指向的数据
int * i=d;//OK
int * j=e;//error,可通过j修改e指向的数据
int & k=f;//error,可通过k修改f引用的数据
const int * l=c;//OK
const int * m=d; //OK,可以将指针常量赋值给常量指针
const int * n=e; //OK
int * const o=c;//error,可通过o修改c指向的数据,不能将常量指针赋值给指针常量
int * const p=d;//OK
int * const q=e;//error,可通过q修改e指向的数据
总上所述,可得出如下赋值规则:
     int <----> const int
    int* ------> const int*
   int* <-----> int*const
   int* ------>const int*const
const int* <------ int*const
   const int* <-----> const int*const
     int*const ------> const int*const
           int& ------> const int&
<---->:代表可以相互赋值。------>:可以单向赋值


二、指针
1、 常量指针:指针指向的数据为常量,不能修改
2、 指针常量:指针本身是常量,不能将指针修改为指向别的变量
3、 指向常量的指针常量:指针指向的数据为常量,指针本身也为常量


三、引用
       引用是变量的别名,引用不占用存储空间,定义引用时必须赋初值,引用一旦初始化,它就维系在一定的目标上,再也不分开。任何对引用的赋值,
  都是对引用所维系的目标赋值,而不是将引用维系到另一个目标上。
       const可以修饰引用,例如:int a=10; const int &b=a; b是一个引用,引用的是一个常量。
       由于引用一旦初始化,就永远绑定在目标上了,所以像“int & const c;”中的const没有意义,在VC6.0下可以编译时给出warning,但可以编译通过。
  
四、函数参数和返回值
1、传值
如果参数是以值传递的,可用const限定函数参数,如:void func(const Type i).这是作了一个约定:变量初值不会被函数f( )改变。
然而,由于参数是以值传递的,因此要拷贝参数,这个约定对函数的调用者来说是隐藏的。以值的形式传递参数时,可以传递常量,
也可以传递变量,所以对函数的调用者都没有任何限制;同时还要拷贝参数,所以对传入的参数本身也没有任何影响。所以它其实是
函数创建者的工具,而不是函数调用者的工具。以值的形式作为函数的返回值时,如const Type g() 同样要建立临时变量,
此时const的意思是该临时变量不能被修改。所以表达式g()是不能成为左值的,例如:如果Type为int,那么g()++就是非法的,
g()出现在等号的左边也是非法的。这种情况下,Type t1=g()和const Type t2=g()都是合法的。
2、传指针
      如果函数的参数是传递指针,如:void func1(Type* t);
                                void func2(const Type* t);
此时就有很大的不同。只能向func1传递Type*类型的变量,而func2可以接受Type*类型的变量,也可以接受const Type*类型的变量。
        同时函数func2不会修改传递的变量,即在函数func2内,*t是不能作为左值的。而函数func1则可以修改传递过来的变量
      函数返回指针,如:Type *func1();const Type*func2();此时,func1()可以作为左值,func1()++是合法的;func2()不能作为左值,
  func2()++是不合法的。同时,在作为右值时,Type* t1=func1()是合法的,而Type*t1=func2()是不合法的。
3、传引用
  果函数的参数是传递引用,如:void func1(Type& t);void func2(const Type& t);此时就有很大的不同。只能向func1传递Type或Type&类型
变量,而func2可以接受Type、Type&类型的变量,也可以接受const Type、const Type&类型的变量。同时函数func2不会修改传递的变量,即
函数func2内,t是不能作为左值的。而函数func1则可以修改传递过来的变量
       函数返回引用,如:Type &func1();const Type&func2();此时,func1()可以作为左值,func1()=****是合法的;func2()不能作为左值,
func2()=***是不合法的。同时,在作为右值时,Type& t1=func1()是合法的,而Type&t1=func2()是不合法的。
五、类中的const
1、修饰成员变量
       类的成员变量可以用const来修饰,const成员变量必须初始化,但是初始化必须放在构造函数的初始化列表里面。
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。
所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。如
class A
{
   const int size = 100; //错误初始化
    A():size(100)//正确初始化
{
}
}
const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。如
class A
{…
   enum {size1=100, size2 = 200 };
int array1[size1];
int array2[size2];
}
枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限。
2、修饰成员函数
       成员函数的参数和返回值都可以用const修饰,此时的意义和第四节中一样。
       const还可以修饰整个成员函数,此时,“const”放在函数参数右括号的右边。代表的意义是,该成员函数不会修改类的成员变量。
  因此const成员函数不能访问非const成员函数(可能修改成员变量),const成员函数可以访问所有的成员变量,从但是不能修改。
  非const成员函数可以访问const成员函数,也可以访问const成员变量,但不能修改const成员变量。
       如果想在const成员函数内修改其一成员变量,可以在类声明里用mutable修饰该成员变量。
       注意,同名的const成员函数和非const成员函数可以进行重载。
3、修饰类的实例
       可以用const修饰类对象,const类对象只能访问类的const成员函数,可以访问类的成员变量(包括非const变量),但是不能修改它们。
  普通类对象可以访问类的所有成员(const或者非const、变量或者函数)。


摘自:http://hi.baidu.com/lijilijun/item/7c6ea0edcea050d9ea34c995#
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值