C/C++中的const限定修饰符

2019-08-30 0 条评论 50 次阅读 0 人点赞

C语言中的const限定修饰符

在C语言中,const修饰的量可以不用初始化:const int a;,const修饰的量不叫常量,叫常变量

int main(){
    const int a = 20;
    int array[a] = {};//这里会报错:应输入常量表达式
    return 0;
}

因而有一个有趣的例子

#include <stdio.h>
int main(){
    const int a = 20;
    int* p = (int*)&a;
    *p = 30;
    printf("%d %d %d \n",a,*p,*(&a));
    return 0;
}

它的结果是30 30 30,原因是,const其实只是在语法上限制了a作左值,其实它的内存是可以访问并且被修改的

C++中的const限定修饰符

C++当中const的含义和C语言当中是不一样的

for(int index = 0; index < 512; ++index)这样的一个循环有两个问题:

  1. 可读性:这个循环的意义不明确;512再此处被称为魔数(magic number),它的重要性再上下文中没有被提及,像是凭空出现的一个数字。
  2. 可维护性:如果在1000行代码中这个512在4%的代码中出现,那么在修改时我们无法知道哪些代码是需要被改变的,否则即使在修改过程中一旦出错哪怕只有一处,也要回头重新检查整个代码。

这样的问题解决并不困难,通过选择一个助记名,可能是bufSize,使程序更具可读性。

//现在条件测试变成与对象作比较,而不是与一个文字常量作比较。
int bufSize = 512;//缓冲区大小
//...
for(int index = 0; index < bufSize; ++index){
    //...
    if(bufSize = 1)//偶然改变了bufSize的值
}

这种方案的问题是bufSize是一个左值,在程序中可能会被偶然修改。

在C++中,“=”是赋值操作符,而“==”是等于操作符。程序员不小心将bufSize的值改变成了1,将导致一个很难追踪的错误(这也是许多编译器会对这种代码产生警告的原因)

const常量

const类型限定符提供了一个解决方案:

它把一个对象转换成一个常量(constant),如const int bufSize = 512//缓冲区大小,定义一个常量bufSize并将其初始化为512,在程序中任何企图改变这个值的代码都将导致编译错误,bufSize被称为只读的(read only)

因为常量在定义以后就不能被修改,所以它必须被初始化。未初始化的常量定义将导致编译错误。

const指针

const离谁近,则谁不可被改变

离对象类型近则对象值不可被改变;离指针近则指针不可被改变

1.指向const对象的指针如const int *ptrint const *ptr

const double minWage = 9.60;

double *ptr = &minWage;
*ptr += 1.40;//修改了minWage!

一般编译器不能跟踪指针在程序中任意一点指向的对象。(这种内部工作需要进行数据流分析,通常由单独的优化器组件来完成)允许非const对象的指针指向一个常量对象,把“试图通过改指针间接的改变对象值”的动作标记为非法的,这对编译器来说是不可行的。因而任何“试图将一个非const对象的指针指向一个常量对象”的动作都将引起编译错误。

这意味着我们必须声明一个指向常量的指针来做这件事

const doubole *cptr
  • cptr是一个指向 double类型的、被定义成const的对象的 指针。cptr本身不是常量,但是可以重新赋值cptr,使其指向不同的对象,但不能修改cptr指向的对象(即指针所指向的对象的值不可修改,但是可以修改指针指向)。
const double *pc = 0;
const double minWage = 9.60;

pc = &minWage;//ok

double dval = 3.14;

pc = &dval;//ok
dav = 3.14;//ok
*pc = 3.14;//错误
  • const对象的地址只能赋值给指向const对象的指针,但是指向const对象的指针可以被赋以一个非const对象的地址。pc = &dval;
  • const指针被修改为指向一个非const对象后,若想通过const指针修改这个对象的值,仍会导致编译错误,因为在程序运行的任意一点上,编译器不能确定指针所指的实际对象。

2. 指向非const对象的const指针 如int *const ptr

int errNum = 0;
int *const curErr = & errNum;//const指针的指向不能修改

curErr是一个指向int类型(非const)对象的const指针。这意味着不能赋值给curErr其他的地址值,但是可以修改curErr指向的值(即const指针的指向不能修改)。

3. 指向const对象的const指针 如const int const *ptr

const double *const ptr = π

ptr是指向被定义为const的double类型对象的const指针。ptr所指向的对象的值以及他的地址本身都不可能被改变增强程序健壮性。void func(const int *a, const int *b);

L_KingMing

这个人太懒什么东西都没留下

文章评论(0)