C++中const限定符的使用

1. const 修饰普通变量

1.1应用场景

比如如下的代码:

int bufSize=512;
for(int index=0;index!=bufSize;++index){
//...
}

定义一个变量代表某一个常数仍有问题:bufsize是可被(有意或无意)修改的。const限定符解决这个问题。它将一个对象转换成一个常量。
修改为:const int bufsize=512;//input buffer size 定义bufsize为常量,并初始化512。这时候bufsize就无法被用户修改了

1.2 const 对象默认为文件的局部变量

要使const变量能够在其他文件中访问,必须显式地指定它为extern。

1.3 定义const变量时必须初始化;修改了const的变量的值不合法

(a)const int buf;//不合法
(b)int cnt=0; const int sz=cnt;
cnt++;sz++;//不合法,修改了const的变量sz的值

2. 引用与const限定符

2.1 什么是引用

引用(reference)就是对象的另一个名字。引用主要用作函数的形式参数。引用是一种复合类型(compound type),通过在变量名前添加“&”符号来定义。
注意:引用只是它绑定对象的另一个名字,作用在引用上的所有操作事实上都是作用在该引用绑定的对象上。
比如:

int ival=1024;
int &refVal=ival;//ok:refVal refers to ival
refVal+=2;//将refVal指向的对象ival加2.
int ii=refVal;//把和ival相关联的值赋给ii。

2.2 const引用

是指向const对象的引用

const int ival=1024;
const int &refVal=ival;//ok:both reference and object are const
int &ref2=ival;//error:nonconst reference to a const object

可以读取refVal但不能修改,因此,任何对refVal的赋值都是不合法的。用ival初始化ref2是不合法的,ref2是普通的非const引用(nonconst reference),
备注:规定将普通的引用绑定到const对象是不合法的。

3. 指针和const限定符:

3.1 指针定义

概念:指针用于指向对象。与迭代器一样,指针提供对其所指的对象的间接访问,只是指针结构更通用些。与迭代器不同的是,指针用于指向单个对象,而迭代器只能用于访问容器内的元素。
具体来说,指针保存的是另一个对象的地址:

string s("Hello world!");
string *sp=&s;//sp hold the address of s

sp中的操作符表明sp是一个指针变量,&s中的&符号是取地址(address—of)操作符,当此操作符用于一个对象上时,返回该对象的存储地址。
备注:
1.避免使用指针和数组:容易产生不可预知的错误,采用vector和迭代器取代一般的数组、采用string类型取代C风格的字符串;
2.如果要使用指针就要避免使用未初始化的指针
3.解引用:如果对左操作数进行解引用,则修改的是指针所指对象的值; 如果没有使用解引用操作,则修改的是指针本身的值。
4.使用(reference)引用和指针都可以间接的访问另一个值,但有重要区别:①引用总是指向某个对象:定义引用时没有初始化时错误的。②赋值行为的差异:给引用赋值修改的是该引用所关联的对象的值,而不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义时进行初始化的原因)。

3.2 指向const对象的指针

指针指向const对象,则不允许用指针来改变其所指向的const值。C++强制要求指向const 对象的指针也必须具有const特性:

const double *cptr;//cptr may point to a double that is const
*cptr=42;//error:*cptr might be const

3.3 const指针``

const指针——本身的值不能修改

int errNumb=0;
int *const curErr=&errNumb;//curErr is a constant pionter

curErr是指向int类型对象的const指针。与其他的const变量一样,const指针的值不能修改,即不能是curErr指向其他的对象。任何企图给const指针赋值的行为都是错误的:

curErr=curErr;//error:curErr is const

与其他const量一样,const指针也必须在定义时初始化。指针所指向对象的值能否修改完全取决于该对象的类型:如:curErr指向的是一个普通的非常量地int型对象,则可以通过curErr修改该对象的值:

 if(*curErr){ errorHandler();
 *curErr=0;//ok:reset value of the object to which curErr is bound

4. const 修饰函数

4.1 const修饰引用形参

1)函数使用非引用的非const形参,可以传递给该函数const实参和非const实参。按值传递方式(创建实参的副本)

const int i=3,j=6;//const must initializedint
k=gcd(3,6);//ok:k initialized to 3

2)函数使用非引用的const类型形参

void fcn(const int i){ 
//...fcn can read but not write to i
}

则在函数中,不可以改变实参的局部副本。由于实参仍是以副本的形式传递的,因此传递给fcn函数可以是const实参和非const实参。

3)函数使用引用类型的const形参
利用const引用避免复制:
编写一个比较两个string对象长度的函数的例子(类类型和大型数组):string可能会很长,避免复制操作,使用const指针(只需知道每个string的size,而不修改string):

bool isShorter(const string &s1,const string &s2){	
return s1.size()<s2.size();
}

备注;对s1和s2是只读的,这样的一个const引用传递和最普通的函数按值传递的效果是一模一样的,他禁止对引用的对象的一切修改,唯一不同的是按值传递会先建立一个类对象的副本,然后传递过去,而它直接传递地址,所以这种传递比按值传递更有效,而且避免了复制。

4.2 const修饰指针形参

参数为指针
void function (const int a); //情况1
void function (const int * a); //情况2
void function (int const * a); //情况3
void function (int * const a); //情况4
情况1:传递过来的参数a在函数中不能被修改(无意义,因为本身就是形参,改不改都不会影响实参)
情况2与情况3相同:a指针所指的内容a 不能修改
情况4:指针a为常量,其地址不能改动,但是
a可以修改(无意义,改不改a指针指向的地址都不影响实参)

5. const修饰类

5.1 const修饰成员函数、成员变量

成员常量不能被修改,可以在初始化列表中赋值,也可以static和const并用,在外部初始化。
const成员函数可以访问类中的所有成员变量(const或非const成员变量),但是都不能修改任何一成成员;
const 成员函数只能调用类中的const成员函数,而不能调用类中的非const成员函数;

5.2 const修饰类对象/对象指针/对象引用

· const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。

6 const使用的建议

  1. 对于单纯的变量,最好以const对象替换#define
  2. 将某些东西声明为const可以帮助编译器侦测出错误用法。const可被施于任何作用域内的对象、函数参数、函数返回类型、成员函数,成员变量。
  3. 当const和non-const有着实质等价的实现时,使用const版本可以避免代码重复。

7 参考

C++ const限定符全解
Effective C++ 中文版(第三版) Scott Meyers
C++ Primer 中文版(第四版) Stanley B.Lippman

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值