2.4 const限定符
关键字const对变量的类型加一限定
const int bufSize = 12;
const所修饰的对象一旦创建后就不能改变其值,所以其修饰的对象必须要初始化。 与非const类型对象相比,const所修饰的对象可以进行大部分非const对象所进行的操作,但是不能被修改或者重新赋值。
默认状态下,const对象只在文件中有效
当以编译时初始化一个const修饰的变量时,编译器将在编译过程把用到该变量的地方都变成对应的值。 (《C++ Primer》)
2.4.1 引用常量
引用常量不能修改它所绑定的对象,非常量引用不能指向常量对象
int i = 10;
const int &r = i;
r = 11;
const int i = 10;
int &r = i;
初始化和对const的引用
引用的类型必须与所引用的对象类型一致,例外: 初始化常量引用时允许用任意表达式作为初始值,只要表达式的结果能够转换称引用类型即可。
int i = 10;
const int &r = i;
const int &r1 = 45;
const int &r2 = r*2;
int &r3 = r1*2;
对const的引用可能引用一个并非const的对象
常量引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未做限定。因为对象也可能是个非常量,所以允许通过其它途径改变常量引用的值。
int i = 10;
const int &r = i;
i = 15;
cout << r << endl;
int &r1 = i;
r1 = 16;
cout << r << endl;
2.4.2 const和指针
指针可以指向常量或非常量,要想存放常量对象的地址的指针必须是被const关键字修饰的,指向常量的指针不能用于改变其指向的对象的值。
const double i = 3.14;
const double *p = &i;
*p = 12;
double *p1 = &i;
指向常量的指针的类型必须和指向的对象类型一致,例外: 指向常量的指针指向了非常量的对象
int i = 10;
const int *p = &i;
i = 15;
cout<< *p << endl;
const指针
指针是对象而引用不是,因此就像其它类型对象一样,允许将指针本身定位常量。常量指针(const pointer)必须初始化,一旦初始化完成,则指针的值(存放的地址)也就不能被改变了。
const int i = 10;
const int *const pip = &i;
int i = 15;
int *const p = &i;
cout << *p << endl;
*p = 45;
cout << *p << endl;
i = 10;
cout << *p <<endl;
int k = 33;
p = &k;
指向常量对象的指针必须是const修饰的指针,指向常量的指针可以存放非常量对象也可以存放常量对象的地址,const指针存放的地址固定不变。
2.4.3 顶层const
指针本身是对象,指针本身是不是常量和指针指向的对象是不是常量是两个独立的问题,为了区分这两个说法,用顶层const和底层const来区别。
类型 | 顶层const | 底层const |
---|
解释 | 指针是常量对象 | 指针指向一个常量对象 | 示例 | int *const p = &i; | int const i = 10;const int *p =&i; |
拓展顶层const和底层const的定义:顶层const指的是任意常量对象,而底层const则与指针和引用等复合类型的基本类型部分有关。
int i = 10;
int *const p1 = &i;
const int *p2 = &i;
const int ci = 12;
当执行拷贝操作的时候,顶层const和底层const有明显区别。顶层const不受影响,因为顶层const所修饰的对象是常量对象,不可被修改,执行拷贝操作并不会改变拷贝对象的值,因此拷入和拷出的对象是否是常量都无影响。
int i = 11;
const int ci = 10;
const int *p1 = &ci;
const int *const p2 = p2;
i= ci;
p1 = p2;
对于底层const,拷入和拷出的对象必须具有相同的底层资格
const int ci = 10;
const int *p2 = &i;
int *p = p2;
2.4.4 constexpr和常量表达式
常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式。字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式。一个对象或表达式是不是常量表达式由其数据类型和初始值共同决定。
const int i = 10;
const int l = i +1;
int s = 2;
const int k = get_size();
constexpr变量
C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为cosntexpr的变量一定是一个常量,且必须用常量表达式初始化。
constexpr int i = 20;
constexpr int l = size();
constexpr变量
声明constexpr时用到的类型成为“字面值类型”,算术类型、引用类型和指针都属于字面值类型,自定义的类、IO库、string类型都不属于字面值类型。 constexpr指针的初始值必须时nullptr或者0,或者是存储于某个固定地址中的对象。 函数体内的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量,而定义于所有函数体外的对象固定不变的地址,可以用来初始化constexpr。
constexpr和指针
在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关
const int *p = nullptr;
constexpr int *q = nullptr;
constexpr将所定义的对象q置为了顶层。
|