const限定符有很多独特的规则,在学习中经常有搞不清楚,概念不清晰等情况,在学习《C++ Primer》一书中,对涉及const的情况作了相应的整理和汇总。
const对象必须初始化。在利用一个对象为const对象初始化时,该对象无论是不是const都无所谓,const对象的常量特征只有在执行改变const对象的操作(该操作不被允许)时才会发挥作用。
consnt对象只在文件内有效,为了能够在多个文件中的共享const对象,必须在变量的定义之前添加extern关键字。
1. const的引用
一般,引用的类型必须与其所引用对象的类型一致,此处有一个例外:在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能够转换成引用的类型即可。
1 | double dval = 3.14; |
编译器会将上述代码变成
1 | const int temp = dval; //由双精度浮点数生成一个临时的整型变量 |
对const的引用可能引用一个并非const的对象,常量引用仅对可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定。
2. 指针和const
指向常量的指针
与引用一样,指针可以指向常量和非常量。指向常量的指针不能用于改变其所指对象的值。指针的类型必须与其所指对象的类型一致,此处有一例外:允许另一个指向常量的指针指向一个非常量对象
1 | const double pi = 3.14; |
常量指针
把*放在const关键字之前用以说明指针是一个常量,即常量指针,指不变的是指针本身而非指向的那个值。常量指针必须初始化。
1 | int errNumb = 0; |
3. 顶层const与底层const
顶层const可表示任意的对象是常量,对任何数据类型都适用,如算术类型、类、指针等;底层const则与指针和引用等复合类型部分有关。指针既可以是顶层const也可以是底层const,顶层const表示指针本身是个常量,底层const表示指针所指的对象是一个常量。
1 | int i = 0; |
执行拷贝操作时,拷入和拷出的对象都必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可转换为常量。
1 | int *p = p3; //错误:p3包含底层const的定义,而p没有 |
4. constexpr和const对指针的不同作用
声明为constexpr类型的变量由编译器来验证变量的值是否时一个常量表达式(是指值不会改变且在编译过程就能得到计算结果的表达式)。限定符conxtexpr仅对指针有效,与指针所指的对象无关:
1 | const int *p = nullptr; //p是一个指向整型常量的指针 |
与其他指针一样,constexpr指针既可以指向常量也可以指向一个非常量:
1 | int j = 0; |
5. 指针、const和类型别名
体会下以下代码
1 | typeodef char *pstring; |
篇string实际上是指向char的指针,const pstring 就是指向char的常量指针,而非指向常量字符的指针。不能尝试把类型别名替换为原来的样子:
1 | const char *cstr = 0;//是对const pstringcstr的错误理解 |
6. 复合类型、const和auto
auto类型说明符是让编译器替我们分析表达式所属的类型。
auto一般会忽略掉顶层const,底层的const则会保留下来,如当初始值是一个指向常量的指针时:
1 | int i = 0; |
要在一条语句中定义多个变量,切记,符号&和*只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一种类型:
1 | auto &m = ci,*p = &ci; //m是对整型常量的引用,p是指向整型常量的指针 |
7. 指针或引用形参与const
形参的初始化与变量的而初始化是一样的,可以适用非常量初始化一个底层const对象,但是反过来不行;同时一个普通的引用必须用同类型的对象初始化。
1 | //reset函数 |
以上是关于const的一些总结和初级理解,希望对您全面掌握const的使用规则有一定的帮助。
本文链接: http://example.com/2020/12/28/C-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bconst/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!