const限定符
用const修饰变量可以表示该变量不能被改变。const对象一旦创建后其值就不能被改变,所以const对象必须初始化。
对象的类型决定了其上的操作,只能在const类型的对象上执行不改变其内容的操作。比如进行类型转换,进行算术运算等等。还可以进行初始化,用const对象初始化非const对象,用非const对象初始化const对象。
默认状态下,const对象仅在文件内有效
const int bufSize = 512 ; //以编译初始化的方式定义一个const对象
编译器将在编译过程中把用到该变量的地方都替换成对应的值。因此,编译器在编译的过程必须知道变量的初始值,如果程序包含多个文件,每个用了const对象的文件都必须能访问到const对象的初始值,因此在每个使用了const对象的文件中都应该有该const对象的定义,为了避免对同一变量的重复定义,默认情况下,const对象被设定为仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同的文件中分别定义了独立的变量。
Q:如何在多个文件中共享同一const对象呢?
A:对于const变量,不管是声明还是定义都添加extern关键字。在const 变量的定义之前添加extern关键字。
const引用
把引用绑定到const对象上,称为对常量的引用。引用也是const ,不能让一个非常量引用指向一个常量对象。
初始化和对const的引用
通常来讲,引用的类型必须和其引用的对象类型一致。有两个例外:
1. 在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型。
2. 对const引用可能引用一个非const的对象。
指针和const
通常指针的类型必须和其所指的对象的类型一致,但是,允许常量指针指向一个非常量对象。
const指针
常量指针必须初始化,一旦初始化完成,指针的值就不能再改变了。
//声明从右向左读
//errNumb 是一个int变量
int errNumb = 0;
//curErr是一个常量指针,指向int变量,curErr不能再指向其他变量,但是可以通过curErr改变errNumb的值
int *const curErr = &errNumb;
//pi是一个double类型的常量,值不能被改变
const double pi = 3.14159;
//pip是一个常量指针,指向double类型的常量,pip指向不能改变,也不能通过pip改变pi的值。
const double *const pip = π
指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全取决于所指对象的类型。
顶层const
指针本身是一个对象,又可以指向另外一个对象。指针本身是不是常量以及指针所指的是不是一个常量是两个互相独立的问题。
用名词顶层const表示指针本身是一个常量,底层const表示指针所指的对象是一个常量。
通常来说顶层const可以表示任意一个变量时const,底层const跟指针、引用等复合类型的基本类型有关系。
在执行对象的拷贝时,常量是顶层const还是底层const区别明显。
顶层const可以进行对象间的拷贝,可以把一个常量指针赋值给一个非常量指针,可以把一个非常量指针赋值给一个常量指针。
但是不能把一个指向常量对象的常量指针赋值给一个指向非常量对象的指针或者常量指针。可以把一个非常量赋值给常量 比如int *可以转化为 const int * 反之则不行。
具有相同底层const可以进行拷贝。
const_expr和常量表达式
常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式。
一个对象或者表达式是不是常量表达式由它的数据类型和初始值共同决定。只有初始值在编译过程就能确定并且数据类型是const才是常量表达式。
constexpr变量
在一个复杂系统中,很难分辨一个初始值到底是不是常量表达式。c++11中规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否一个常量表达式。
声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
不能使用普通函数作为constexpr变量的初始值,新标准允许定义一种特殊的constexpr函数,这种函数应该足够简单以使得编译时就能确定结果。就可以用constexpr函数去初始化constexpr变量了。
字面值类型
算术类型、引用和指针都属于字面值类型,指针和引用都能定义成constexpr,但他们的初始值却受到严格的限制,一个constexpr指针的初始值必须是nullptr或0,或者是存储于某个固定地址中的对象。
函数体内定义的变量一般来说并非存放在固定的地址中,因此constexpr指针不能指向这样的变量,定义于所有函数体之外的对象其地址固定不变,能用来初始化constexpr指针。
允许函数定义一类范围超过函数本身的变量,这类变量和定义在函数体之外的变量一样有固定地址。constexpr引用能绑定到这样的变量上,指针也能指向这样的变量。
指针和constexpr
用constexpr修饰的指针仅表达指针是const,与指针指向的对象无关。
constexpr把它所定义的对象置为了顶层const。