C++学习笔记:C的继承与超越——const关键字

来源:互联网 发布:淘宝网店网页制作 编辑:程序博客网 时间:2024/05/21 09:36
C语言中也有const关键字,但是它却是一个不地道的常量关键字。
const int MAX = 100;int a[MAX];

在C语言编译器下,定义数组的这条语句往往会报错。定义数组大小需要的是常量表达式,而编译器并不认为MAX是一个常量表达式,哪怕定义MAX时加了关键字const。
在C中,const意味着不能修改,但不是常量。
而在C++编译器下,上述代码是没有问题的。

不过有的时候,C++中使用const修饰的表达式也不一定是常量表达式,例如:

const int sz = get_size();

这就是另一个关键字constexpr的故事了。

const与引用

const int a = 666;const int &ra = a; //ra是对常量a的引用ra = 999;          //错误,ra是对常量的引用,不能修改int &ra_2 = a;     //错误,a是常量,不能让一个非常量引用绑定一个常量
int b = 666;const int &rb = b; //正确,可以将一个对常量的引用绑定到一个变量上rb = 999; //错误,引用“认为”它绑定的是一个常量,因此不能通过引用修改变量的值

此外,常量引用可以绑定一个临时量对象,而非常量引用是不可以的。

int a = 666;double b = 999.99;const int &r1 = 0.0;const int &r2 = a * 99;const int &r3 = a * b;// 以上全部正确,以下全部错误int &r4 = 9; int &r5 = a * 2;

以r3为例,看一看常量引用的过程中到底发生了什么:

const int temp = a * b;const int &r3 = temp;

从以上代码就可以理解为什么非常量引用不可以绑定临时量了。

const与指针

这是一个比较坑的地方,关于const关键字限定的究竟是指针自身还是指针所指向的对象的问题有时候会困扰着我们。而引用不存在这方面的苦恼,因为引用本身就是被const的,一旦初始化时与其他对象绑定,之后便不可修改绑定对象,所以:

int a = 666;const int &ra_1 = a;// 正确int const &ra_2 = a;// 正确int& const ra_3 = a;// 错误

在看实例之前,首先引入两个概念:顶层const和底层const。
顶层const是指当前定义的对象本身是一个常量。
底层const是指不能通过当前定义的对象去改变当前定义的量所指向的对象。
让我们来看一看指针的例子:

int a = 666;const int b = 999;//顶层const,b的值不允许改变const int *pa_1 = &a;//底层const,pa_1是一个指针(允许被改变),指向const int类型的a,虽然a是变量,由于const修饰,所以不能通过pa_1修改aconst int *pb_1 = &b;//底层const,pb_1是一个指针(允许被改变),指向const int类型的bint *pb_2 = &b;//错误,指向const int类型的指针必须是有顶层const限定的int*类型int* const pa_2 = &a;//顶层const,允许通过pa_2修改a,但pa_2本身不允许被修改const int* const pa_3 = &a;//即是顶层const也是底层const,既不能修改pa_3指针本身,也不能通过pa_3修改aint const &rb = b;//限定引用的const都是底层const

看一个const是顶层const还是底层const,关键要看const是在*左边还是*右边,在*左边的是底层const,在*右边的是顶层const。
更让人费解的是对pointer to const 和 const pointer的中文翻译,一组翻译是指向常量的指针和常量指针,另外一组是常量指针和指针常量,同一个名词却可以是完全相反的两个意思,其实看英文完全可以区分,不纠结中文翻译了。

在对象拷贝的过程中,顶层const和底层const的待遇也是不一样的,先看顶层const,显然顶层const只能放在等号右边:

int i = b;pa_1 = pa_2;

上面的操作均是合法的。
底层const放在等号右边的时候就要小心了:

int *p1 = pa_1;//错误,pa_1中的const是底层const,不允许通过pa_1修改a,而这样的赋值存在着使a被修改的风险pa_1 = pb_1;//正确,都是底层const

总之,底层const的值不能赋给非底层const的对象,以避免常量被修改的危险。

const与typedef

《C++ Primer》中举了一个例子,说明了const修饰自定义类型时的作用对象。

typedef char *pstring;const pstring cstr = 0;const pstring *ps;

下面的理解是错误的:

const char *cstr = 0;const char **ps;

正确的理解是,这里的const是顶层const而不是底层const,即cstr是一个const pointer to char,而ps是一个pointer to const pstring,即pointer to const pointer to char。

const和auto以及decltype还有一些不得不说的故事,还是放到下一篇去讲吧,今天已经够晕了。

0 0
原创粉丝点击