文章目录
在实际场景中,希望一个变量不能被改变,就需要使用关键字const对变量的类型加以限定。
1、初始化和const
因为const对象一旦创建后其值就不能在改变,因此const对象必须初始化。
①默认情况下,const对象仅在文件内有效
定义了一个const对象之后,编译器将在编译过程中把用到该变量的地方都替换成对应的值。
若想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。
2、const的引用
将引用绑定到const对象上,称为对常量的引用(即“对const的引用”),常量的引用与普通的引用不同的是:不能被用作修改它锁绑定的对象。
const int nCount = 128;
int &nRef = nCount; //错误
const int &nRef = nCount; //正确
3、初始化和对const的引用
一般情况下,引用的类型必须与其所引用对象的类型一致,但有例外的情况,初始化常量引用就是一种。初始化常量引用时允许用任意表达式作为初始化,只要表达式的结果能转换成引用的类型即可,允许为一个常量引用绑定非常量的对象、字面值,甚至是表达式。
我们看看下面的代码会发生什么:
double dVal = 3.14159265;
const int &nRef = dVal;
实际上编译器会解析成:
double dVal = 3.1415926500000002;
const int & nRef = static_cast<const int>(dVal);
这样看的话,编译器先将dVal转换成const int类型的变量,这个变量是临时量(就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象),因此变成了如下:
double dVal = 3.1415926500000002;
const int nTemp = static_cast<const int>(dVal);
const int & nRef = nTemp ;
基本不会将const的引用绑定到临时量上,因此const的引用时不可修改的,C++就默认这种行为是非法的。
4、对const的引用可能引用一个非const的对象
常量引用仅对引用可参与的操作做了限定,对于引用的对象本身没有做限定,因此对象是可修改的。
int nVal = 32;
int &nRef = nVal;
const int &nRef2 = nVal;
nRef = 23; //正确,nRef非常量
nRef2 = 43; //错误,nRef2是常量引用
5、指针和const
指向常量的指针不能用于改变其所指对象的值,若想存放常量对象的地址,只能使用指向常量的指针。
const int nVal = 32;
int *pInt = &nVal; //错误
const int* pInt1 = &nVal; //正确
指向常量的指针没有规定其所指的对象必须是一个常量,仅仅要求不能通过指针改变对象的值。
6、const指针
常量指针必须初始化,一旦初始化完成,它的值就确定了。指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全依赖于所指对象的类型。
7、顶层const
顶层const:指针本身是个常量
底层const:指针所指的对象是一个常量
顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用;底层const则与指针和引用等复合类型的基本类型部分有关。
int nCount = 43;
int *const p = &nCount; //顶层const
const int i = 12; //顶层const
const int *p1 = &i; //底层const
const int *const p3 = p1; //const int是底层const,另一个是顶层const
const int &nRef = i; //用于声明引用的const都是底层const
是否可以认为声明的const都是底层const呢?
当执行对象的拷贝操作时,常量是顶层const还是底层const的区别明显,其中顶层const不受影响。底层const的限制不能忽视,当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格,或2个对象的数据类型必须能够转换。
8、const修饰指针变量
有3种情况:
①const修饰指针指向的内容
②const修饰指针
③const修饰指针和指针指向的内容
const int* p = 109; //指针指向的内容不可修改,简称左定值,因为const位于*的左边
9、const在c和c++中的区别
1)C++中的const正常情况下是看成编译期的常量,编译器并不为const分配空间,只是在编译的时候将其值保存在名字表中,并在适当的时候折合在代码中;
2)C++中,const默认使用内部连接,而C中使用外部连接;
内连接:编译器只对正被编译的文件创建存储空间,别的文件可以使用相同的表示符或全局变量。C/C++中内连接使用static关键字指定;
外连接:所有被编译过的文件创建一片单独存储空间。一旦空间被创建,连接器必须解决对这片存储空间的引用。全局变量和函数使用外部连接。通过extern关键字声明,可以从其他文件访问相应的变量和函数。
10、constexpr和常量表达式
常量表达式是指值不会改变且在编译过程就能得到计算结果的表达式。一个对象或表达式是不是常量表达式是由它的数据类型和初始值共同决定。
在C++11规定,允许将变量声明为constexpr类型以便由编译器验证变量值是否是一个常量表达式。
注意:在constexpr声明中若定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。constexpr会把其所定义的对象置为顶层const。