const 限定符
const int bufSize = 512;
// 限定后不能改变!
const int k; // 不对!!!k是一个未经初始化的常量!
int i = 42;
const int ci = i;
int j = ci; // ci只有被改变时才会发挥作用,作为其他操作值仍然起作用!
const 只在文件中起作用!!,如果想全局起作用需要extern
const 的引用
可以把引用绑定到其他对象上,我们称之对常量的引用(reference to const)
对常量的引用,不能被用作修改它所绑定的对象
const int ci = 1024;
const int &ri = ci;
ri = 42; // 错误!!!ri是对常量的引用
int &r2 = ci; // 错误!!,试图让一个非常量引用指向了一个常量对象
引用的类型必须和所引用的对象的类型一致, 但是有两个例外,
1 :
int i =42;
const int &r1 = i; // 正确!!
const int &r2 = 42; // 正确!!
const int &r3 = r1*2; // 正确!!
int &r4 = r1*2; // 错误!!r4是一个普通的非常量的引用!
double val = 3.14;
const int &ri = dval;
此处的ri 引用了一个int型的数,对ri 的操作应该是整数运算,但是dval是一个double,因此,其实编译器是做了如下操作!
const int temp = dval;
const int &ri = temp;
在这种情况下,ri绑定了一个临时量对象!
int i = 42;
int &ri = i;
const int &r2 = i;
r1 = 0;
r2 = 0; // 错误!!!,因为r2是个常量引用!!,不允许通过r2 修改i 的值,
2.4.2 指针和const
指向常量的指针(pointer to const ) 不能用于改变其所指对象的值,要想存放常量的地址,只能使用指向常量的指针
const double pi = 3.14;
double *ptr = π // 错误!!,ptr是一个普通指针,
const double *cptr = π
*cptr = 42; // 错误!不能给*cptr 赋值
指针类型必须与其指向的对象类型一致,但是有两个例外,
1 允许指向常量的指针,指向非常量
double dval = 3.14;
cptr = &dval ; // 可以,但是不允许通过cptr改变dval 的值,(但是可以通过其他途径改变)
const 指针!
指针是对象,而引用不是,因此就像其他对象类型一样,允许把指针本身定义为常量!!!
常量指针,必须初始化,而且一旦初始化,则它的值也就不能改变了
int errNumb = 0;
int * const curErr = & errNumb; // 指针只能一直指向 errNumb
const double pi = 3.14159;
const double *const pip = π // pip 是一个指向常量对象的常量指针
从右往左读!!!
2.4.3 顶层 const
用顶层(top - level const )表示指针本身就是个常量
用底层( low- level const ) 表示指针所指的对象是一个常量
执行copy 操作的时候,常量是顶层,几乎没有影响
但是底层const 的限制不容忽略!!
拷贝和拷出的对象必须具有相同的底层const 资格,或者两个对象类型必须能相互转换!一般来说,非常量能转换成常量,反之不行!
2.4.4 constexpr 和常量表达式
常量表达式(const expression) 是指 值不会改变,并且在编译过程中就能得到计算结果的表达式。显然字面值属于常量表达式
const int max_files = 20; // 是常量表达式
const int limit = max_file +1; // 是常量表达式
int staff_size = 27; // 不是常量表达式!首先就不是常量!!
const int sz = get_size(); //不是!因为sz 的值,只有在运行过程中才能获取到!!
C++11 新标准规定,允许将变量声明为 constexpr 类型,以便由编译器来验证变量的值,是否是一个常量表达式!
constexpr int sz = size(); 只有当size是一个constexpr函数时,这才是一条正确的声明语句!
字面值类型:
尽管指针和引用都能定义成为constexpr ,但它们的初始值却受到严格限制,一个constexpr 指针的初始值必须是nullptr 或者0,或者存储与某个固定地址的对象!