以前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点。知识用时方恨少,这一段时间正好各类笔试题,其中关于const的用法也是层出不穷,因此疲于在书本上各类翻,这里汇总一下,加深本身的印象的同时,也方便之后查阅和学习。菜鸟一个,如有错误,望指正! 程序员
常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。无论出如今任何上下文都是为这个目的而服务的。 面试
const修饰符能够把对象转变成常数对象,意思就是说利用const进行修饰的变量的值在程序的任意位置将不能再被修改,就如同常数同样使用!任何修改该变量的尝试都会致使编译错误: 数组
注意:由于常量在定之后就不能被修改,因此定义时必须初始化: 函数
对于类中的const成员变量必须经过初始化列表进行初始化,以下所示: 学习
在全局做用域里定义非const变量时,它在整个程序中均可以访问,咱们能够把一个非const变量定义在一个文件中,假设已经作了合适的声明,就能够在另外的文件中使用这个变量: this
与其余变量不一样,除非特别说明,在全局做用域声明的const变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其余文件访问。经过指定const变量为extern,就能够在整个程序中访问const对象。 spa
注意:非const变量默认为extern。要使const变量可以在其余文件中访问,必须在文件中显式地指定它为extern。 3d
const引用是指向const对象的引用: 指针
能够读取但不能修改refVal,所以,任何对refVal的赋值都是不合法的。这个限制有其意义:不能直接对ival赋值,所以不能经过使用refVal来修改ival。同理,用ival初始化ref2也是不合法的:ref2是普通的非const引用,所以能够用来修改ref2指向的对象的值。经过ref2对ival赋值会致使修改const对象的值,为防止这样的修改,须要规定将普通的引用绑定到const对象是不合法的。 const 引用能够初始化为不一样类型的对象或者初始化为右值。如字面值常量: 对象
一样的初始化对于非const引用倒是不合法的,并且会致使编译时错误。其缘由很是微妙,值得解释一下。观察将引用绑定到不一样的类型时所发生的事情,最容易理解上述行为。对于下一段代码:
编译器会将这些代码转换为一下形式:
咱们发现编译器会建立一个int型的暂时变量存储dval,而后将ri绑定到temp上。
注意:引用在内部存放的是一个对象的地址,它是该对象的别名。对于不可寻址的值,如文字常量,以及不一样类型的对象,编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它。
若是ri不是const,那么能够给ri赋一新值。这样作不会修改dval的,而是修改了temp。指望对ri赋值会修改dval的程序员会发现dval没有被修改。仅容许const引用绑定到须要临时使用的值彻底避免了这个问题,直接告诉程序员不能修改,由于const引用是只读的哈~(其实就是避免程序员心理预期产生反差。。。)
注意:非const引用只能绑定到与该引用相同类型的对象。 const引用则能够绑定到不一样但相关的类型的对象或绑定到右值。
若是咱们在自由存储区中建立的数组存储了内置类型的const对象,则必须为这个数组提供初始化: 由于数组元素都是const对象,没法赋值。实现这个要求的惟一方法是对数组作值初始化。
C++容许定义类类型的const数组,但该类类型必须提供默认构造函数:
这里便会调用string类的默认构造函数初始化数组元素。
const限定符和指针结合起来常见的状况有如下几种。
C++为了保证不容许使用指针改变所指的const值这个特性,强制要求这个指针也必须具有const特性:
这里cptr是一个指向double类型const对象的指针,const先顶了cptr指向的对象的类型,而并不是cptr自己,因此cptr自己并非const。因此定义的时候并不须要对它进行初始,若是须要的话,容许给cptr从新赋值,让其指向另外一个const对象。但不能经过cptr修改其所指对象的值。
而咱们将一个const对象的地址赋给一个普通的非const指针也会致使编译错误。
不能使用void*指针保存const对象的地址,必须使用const void*类型的指针保存const对象的地址。
下面使人头晕的一个问题来了----à 容许把非const对象的地址赋给指向const对象的指针,例如:
可是咱们不能经过cptr指针来修改dval的值!!!即便它指向的是非const对象。
而后,咱们必定要知道,不能使用指向const对象的指针修改基础对象,然而若是该指针指向了非const对象,可用其余方式修改其所指的对象,因此事实上,能够修改const指针所指向的值的,可是不能经过const对象指针来进行而已!以下所示:
经过以上,咱们知道指向const对象的指针 确切的讲: 自觉得指向const的指针!
C++中还提供了const指针——自己的值不能被修改。
![]()
咱们能够从右往左把上述定义语句读做"指向int型对象的const指针"。与其余const量同样,const指针的值不能被修改,这意味着不能使curErr指向其余对象。Const指针也必须在定义的时候初始化。
指针自己是const的试试并无说明是否能用改真真修改其所指向的对象的值。指针对象的值可否修改彻底取决于该对象的类型。
以下能够这样定义:
![]()
这样pi_ptr首先是一个const指针,而后其指向一个const对象~~~
在一个类中,任何不会修改数据成员的函数都应该声明为const类型。若是在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提升程序的健壮性。使用const关键字进行说明的成员函数,称为常成员函数。只有常成员函数才有资格操做常量或常对象,没有使用const关键字说明的成员函数不能用来操做常对象。常成员函数说明格式以下:
<类型说明符> <函数名> (<参数表>) const;
其中,const是加在函数说明后面的类型修饰符,它是函数类型的一个组成部分,所以,在函数实现部分也要带const关键字。下面举一例子说明常成员函数的特征。
既然const是定义为const函数的组成部分,那么就能够经过添加const实现函数重载咯。
其中print成员函数就实现了两个版本~~~ 重载哦,输出结果为 5,52。 const对象默认调用const成员函数。
const修饰函数返回值其实用的并非不少,它的含义和const修饰普通变量以及指针的含义基本相同。以下所示:
通常状况下,函数的返回值为某个对象时,若是将其声明为const时,多用于操做符的重载。一般,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的状况。缘由以下:若是返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例) ,则返回值具备const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,而且不容许对其进行赋值操做,这在通常状况下不多用到。
这样的一个const引用传递和最普通的函数按值传递的效果是如出一辙的,他禁止对引用的对象的一切修改,惟一不一样的是按值传递会先创建一个类对象的副本, 而后传递过去,而它直接传递地址,因此这种传递比按值传递更有效.另外只有引用的const传递能够传递一个临时对象,由于临时对象都是const属性, 且是不可见的,他短期存在一个局部域中,因此不能使用指针,只有引用的const传递可以捕捉到这个家伙.
其中关于static、const、static cosnt、const static成员的初始化问题:
在一个类里创建一个const时,不能给他初值
![]()
类中的static变量是属于类的,不属于某个对象,它在整个程序的运行过程当中只有一个副本,所以不能在定义对象时 对变量进行初始化,就是不能用构造函数进行初始化,其正确的初始化方法是:
数据类型 类名::静态数据成员名=值
最后经过一个完整的例子展现以上结果:
![]()
若是函数须要传入一个指针,面试官可能会问是否须要为该指针加上const,把const加在指针不一样的位置有什么区别;若是写的函数须要传入的参数是一个复杂类型的实例,面试官可能会问传入值参数或者引用参数有什么区别,何时须要为传入的引用参数加上const。 const是用来声明一个常量的,当你不想让一个值被改变时就用const,const int max和int const max 是没有区别的,均可以。不涉及到指针const很好理解。一旦涉及到指针,则比较容易出问题。
若是const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向的对象为常量;若是const位于星号的右侧,const就是修饰指针自己,即指针自己是常量。
所以,[1]和[2]的状况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种状况下不容许对内容进行更改操做,如不能*a = 3 ;[3]为指针自己是常量,而指针所指向的内容不是常量,这种状况下不能对指针自己进行更改操做,如a++是错误的;[4]为指针自己和指向的内容均为常量。
若是理解了上面的全部信息,我相信应该问题不大。仅供参考~~~ 但愿你们热烈讨论哈。 好了,先写到这里,在之后须要补充我再加东西吧。。。敲得手疼~~~ ~!!!