C++语言中const关键字用法总结

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C++语言中const关键字用法总结

一、const是什么

在C/C++ 语言中,const关键字是一种修饰符。所谓“修饰符”,就是在编译器进行编译的过程中,给编译器一些“要求”或“提示”,但修饰符本身,并不产生任何实际代码。就const 修饰符而言,它用来告诉编译器,被修饰的这些东西,具有“只读”的特点。在编译的过程中,一旦我们的代码试图去改变这些东西,编译器就应该给出错误提示。

所以,const修饰符的作用主要是利用编译器帮助我们检查自己代码的正确性。我们使用const在源码中标示出“不应该改变”的地方,然后利用编译器,帮助我们检查这些地方是否真的没有被改变过。如果我们不小心去修改了这些地方,编译器就会报错,从而帮助我们纠正错误。使用const和不使用const,对于最终编译产生的代码并没有影响。

虽然const对于最终代码没有影响,但是尽可能使用const,将帮助我们避免很多错误,提高程序正确率。

二、const可以修饰哪些对象

在上面已经提到过了,const是一种修饰符,那它可以作为哪些对象的修饰符呢?下面列举了一些C/C++中用到const的地方。

1,const变量

2,const指针

3,const引用

4,const类

5,类的const成员变量

6,类的const成员函数

7,const修饰函数的形参与返回值

下面我们分别讨论上面几种情况下,const的用法。

三、const与变量

当一个变量被const修饰后,具有以下几个特点:

1)该变量只能读取不能修改。(编译器进行检查)

2)定义时必须初始化。

3)C++中喜欢用const来定义常量,取代原来C风格的预编译指令define。

1 const int var; // Error:常量变量"var"需要初始化设定项

2 const int var1 = 42;

3 var1 = 43; // Error:表达式必须是可以修改的左值

上面代码中第一行和第三行都有错误,注释便是编译器给出的错误提示。

另外注意,在使用const变量作为数组的下标时,变量的值一定要是一个常量表达式(在编译阶段就能计算得到结果)。

1 const int sz = 42;

2 int iAr[sz];

3 const int sz1 = size(); // size()必须是一个返回常量的函数

4 int iAr1[sz1];

5

6 int var = 42;

7 const int sz2 = var;

8 int iAr2[sz2]; // error:sz2只有运行时才知道值

四、const与引用

我们知道,引用必须在定义的时候赋值,这样就会所引用的变量绑定在一起并作为它的一个别名,在程序中的其他地方,是不能让引用再与其他对象绑定。这个特性,让引用看起来就像是const对象一样,一旦定义后将不能更改。所以并不存在const的引用。

但是我们却可以引用一个const的对象(变量),我们称之为对常量的引用,与普通的引用不同的时,对常量的引用不能被用作修改它所绑定的对象。

1 const int ci = 1024;

2 const int &r1 = ci;

3 r1 = 42; // Error:r1是对常量的引用

4 int & r2 = ci; //Error:不能将一个非常量引用指向一个常量的对象

我们知道,引用的类型必须与其所引用对象的类型一致,如下面的代码:

double dval = 3.14;

int& ri = dval; // Error:无法用double类型的值初始化int&类型的引用(非常量限定) 上述代码为何不行?

此处ri引用了一个int型的整数。对于ri的操作数应该是整数运算,但是dval却是一个双精度的浮点数而非整数。因此为了确保让ri绑定一个整数,编译器把上述代码变成了如下形式:

double dval = 3.14;

int temp = dval;

int& ri = temp;

其中temp是一个临时变量,而ri绑定了一个临时量,所以当ri改变时,并没有改变davl的值,所以这种引用是无效的。

也许你注意到了,当我们把double变量绑定在一个int&类型上时,编译器提示后有个括号:非常量限定。这说明如果是一个常量的引用,则有可能是通过的,显然下面的代码就没有任何问题:

double dval = 3.14;

const int& ri = dval;

因为在这里,ri是一个常量引用,我们并不想通过ri改变dval的值,只要能读到dval 对应的int型的值就行。

五、const与指针

我们知道,指针与引用不同,指针本身是一个对象,所以存在常量指针,这种指针在

定义并初始化后,便不能再指向其他变量。用来修饰这种常量指针的const,我们称之为"顶层const"。

与顶层指针对应的是底层指针,这种指针指向一个const修改的对象,这一点上就有点像是常量的引用。

对于指向常量的指针或引用,都有以下规则:

1)可以将一个非const对象的地址赋给一个指向const对象的指针

2)可以将一个非const对象的地址赋给一个指向非const对象的指针

3)可以将一个const对象的地址赋给一个指向const对象的指针

4)不可以将一个const对象的地址赋给一个指向const对象的指针。

1 int var;

2 const int ci = 42;

3

4 int *p1 =& var;

5 int *p2 = &ci; // Error,const int* 不能用于初始化int*

6 const int *p3 = &var; //ok

7 const int *p4 = &ci; // ok

还有一种指向const对象的const指针,这种指针首先表明,本身是一个const指针,一旦初始化后不能指向其他对象;其次,它本身所指向的对象也是一个常量,即不能通过指针修改对象的值。

const int var = 42;

const int* const p = &var;

这里再强调一点,const只是给编译器看的,我们可以很轻松的骗过编译器,并看看编译器都做了什么:

1 const int var = 42;

2 int* p = (int*)&var;

3 *p = 20;

4 cout << var << endl; //42

5 cout << *p << endl; //20

我们在代码的第2行,用一个类型转换强制的,把一个非const指针指向了一个const 对象。

但是后面我们通过这个指针来修改这个值,却没有生效,原因呢?

那是因为编译器在编译阶段发现var是一个常量,所以在编译目标代码时已经将var的地方都用42进行了替换。

六、const与类

其实类定义的对象,与普通的变量是一样的,用const修饰时,说明这个类是一个常量类对象,这个对象有下面2个特点:

1)不能改变其成员变量(非mutalbe成员)

2)不能调用其非const成员函数

1 class AClass{

2 public:

3 int m_var;

4 mutable int m_mutable_var;

相关文档
最新文档