#【概括】
在 C++ 中,指针常量和常量指针是两个有区别的概念。
#【指针常量 】
指针常量——自己是常量的指针(int *const p)
指针是形容词,常量是名词。这回是以常量为中心的一个偏正结构短语。那么,指针常量的本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针。
它的值(即存储的内存地址)是不可修改的,但可以通过解引用来访问或修改指针所指向的对象。指针常量本身是不可修改的,一旦初始化后,就不能再指向其他内存地址。
指针常量的值是指针,这个值因为是常量,所以不能被赋值。(指针地址不能改,指针指向的值能改)
就是所谓的“自己是常量的指针”。“p自己不能修改但能够经过p修改其所指”。 因为p自己是const的,因此在编译的时候必须知道p的值(即p所指向的东西的地址),因此在声明p的同时必须初始化p。
#【常量指针】
常量指针——指向常量的指针(const int *p,int const *p)
常量是形容词,指针是名词,以指针为中心的一个偏正结构短语。这样看,常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针(变量)。
指针指向的对象是常量,那么这个对象不能被更改。(指针地址能改,指针指向的值不能改)
这里注意,所谓“指向常量”只是这个指针的“一厢情愿”,只是一种效果上的等价。事实上,const int *p=&a; a既能够是常量(const int a=10;)又能够是变量(int a=10;),但p一厢情愿地认为它所指的就是一个常量,因此它不容许经过本身来修改所指,这就形成一种效果上的等价——从p的角度看,它所指的“的确”是常量。因此,对“指向常量的指针”的最佳理解应为:咱们不能经过该指针修改它所指向的东西(常量或者变量)。
注意,const int *p=&a;只是说不能经过p来修改a,若是a自己不是const的,经过其它方式修改a天然是能够的(例如直接++a)。
另一点,因为p自己只是一个普通的指针,因此容许在声明时不初始化。但须要注意的是,咱们只是说能够,但并不提倡这样作。在任什么时候候都不该该让指针无所指,若是在声明一个指针时还不知道让它指向谁,就先将其初始化为nullptr或NULL(nullptr是C++11新特性,用它比用NULL更安全些,这里不详细介绍)。
#【指向常量的指针常量】
指向常量的指针常量——所指和自己都是常量的指针(const int* const p)
顾名思议,指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。
因为是一个指针常量,那么它指向的对象当然是一个指针对象,而它又指向常量,说明它指向的对象不能变化。(指针地址不能改,指针指向的值不能改)
相信看到这里还是有点懵,其实很多书籍,不知道是不是翻译问题,他的指针常量和常量指针很混乱,术语名称不统一,所以只需要自己理解就行,不建议用指针常量,常量指针来区分,很混淆。
下面是一条口诀:
先找到*,而后看*的两边,右边是对指针p自己的限定,左边是对p所指向的东西的限定。
例如:
1.const int *p
*的右边没有限定成分,代表p就是咱们熟悉的普通指针,p的内容(即值,也就是它指向的东西的地址)是能够改变的;*的左边是const int,代表p指向的东西是一个const的int,咱们不能经过p来修改这个int,由于它是const的。(关于“不能经过p来修改”,也就是不同通过*p=xxx解引用修改他,咱们后边还会详细解释)
2.int* const p
*的右边是const,代表p自己是const的,咱们不能对p的内容进行修改(例如++p;是不能够的),*的左边是int,即p指向的东西是普通的int,咱们能够经过p来修改它(例如*p=100;是能够的)。
3.const int* const p
*的右边是const,代表指针p自己是const的,*的左边是const int,代表p指向的int也是const的。即这种状况下,p自己不能修改,同时也不能经过p修改它所指向的那个int。