关于const

                             #  关于const

如果你需要定义这样与一个变量,它的值不能改变,在c/c++中,我们可以用const 限定符来修饰这个变量

const int a;//error,const修饰的变量必须初始化
const int a = 10;
a++;//error,试图修改这个变量

const对象默认为文件局部变量,如果相要让其他文件访问const变量,声明的时候要加extern显式声明。

关于指向常量的指针和常量指针:

指向常量的指针:该指针指向一个常量的地址,注意的是,也可以把非常量的地址赋值给指向常量的指针。

const int a = 10;
int *b = &a;//error 不能将const int *赋值给int *
const int *c = &a;// ok
*c = 10;//error; *c的值不能改变。
c = &b;//ok,可以改变c存放的地址,与下做对比。

常量指针:该指针是一个常量,即指针声明时必须初始化,初始化后指向的地址不能够改变

int a = 10;
int c = 20;
int* const b = &a;//ok,将a的地址赋值给b
b = &c;//error,不能改变b存放的地址。
/*
与上做对比
*/
*b = 100;//ok,可以改变b存放的地址中存储的值

这里引入两个名词:顶层const和底层const,指针本身是一个对象,指针指向的另外一个对象,指针是常量和指针指向的是一个常量是两个独立的为题,在这里,顶层const表示指针本身是一个常量,底层const表示指针指向的对象是一个常量。

int i = 0;
int* const cptr = &i;
cptr = nullptr;//error,cptr是一个顶层const。
const int *ptr2 = &i;
ptr2 = nullptr;//ok,ptr2是一个底层const。

const和constexpr:

需要注意的是const定义的变量并不是严格的常量表达式,常量表达式需要编译时就能得到值,c++有些情况下需要用到常量表达式,例如数组边界,case语句的选择器,位域长度规范,枚举初始值设定项。

const int a = 10;//a 是常量表达式。
const int b = get_num();//b不是一个常量表达式,因为要在运行时才能得到值,实际上现在的编译器会将简单的函数优化在编译期就得到结果。

因此我们在程序中不得不去判断一个const定义的变量是不是一个常量表达式,这会增加代码的复杂度,而且阅读难度增加。

在C++11规范中引入了constexpr,规定constexpr定义的变量必为常量表达式,如果constexpr修饰定义的常量不能在编译期计算得到结果的话,会引发编译错误。

另外constexpr定义的指针必为一个顶层const。

int func(){
    int a = 0;
    cin>>a;
    return a;
}
constexpr int a = 10;//ok
constexpr int b = func;//error,b的值必须用一个常量表达式初始化。
const int c = func;//ok;但是c并不是一个常量表达式
constexpr int *cptr = nullptr;//cptr为一个顶层const。

引用:

1.《C++primer第五版》

2.https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/const

posted @ 2021-01-19 21:27  Emiria  阅读(55)  评论(0编辑  收藏  举报