C++中const的“就近原则”

在做题的时候,编译时经常会遇到关于const的坑,如果在平时不是常用的话就会很容易忘记,在这里整理一下const的“就近原则”的笔记。

指针

要理解就近原则首先要明白指针。
指针(pointer),可以看作指向(point to)。与引用类似,实现了对其他对象的间接访问。
但有两个不同之处:
1.指针本身就是一个对象,允许对指针赋值和拷贝,并且指针在周期内可以先后指向几个不同的对象(除非是const指针)

const指针是指针变量的值一经初始化,就不可以改变指向,初始化是必要的。其定义形式如下:
int * const pTwo; //指向整形的常量指针 ,它不能在指向别的变量,但指向(变量)的值可以修改。(结合之后会说的就近原则理解记忆。)

2.指针无需在定义时赋初值(若未初始化,它将有一个不确定得值)。

简单示例

{
	int a = 0;
	int b = 1;

	int* const p1 = &a;			//p1是指向int型数据的const指针,指向不可改变。
	int* (const p11) = &a;		//p11与p1相同。
	const int *p2 = &a;			//p2是指向int型数据的指针,指向可以改变,
								//但不可以通过p2改变指向地址上的值。
	const int(*p22) = &a;		//p22与p2相同。
	const int* const p3 = &a;	//p3是指向in型数据的const指针,不能通过p3改变指向地址上的值。
	p1 = &b;		//报错(指针指向不能被修改)
	*p1 = b;
	p2 = &b;
	*p2 = b;		//报错(指针指向的内容不能被修改)
	p22 = &b;
	*p22 = b;		//报错(指针指向的内容不能被修改)
	p3 = &b;		//报错(指针指向不能被修改且指针指向的内容不能被修改)
	*p3 = b;		//报错
}

读const指针的方法,我们可以学习《C++Primer》上 P56的方法,也就是“从右往左读”。

int errNumb =0;
int *const curErr = &errNumb;
const double pi = 3.1415;
const double *const pip = π

此例中,从右往左,离curErr最近的是const,意味着curErr本身是一个常量对象,继续往左看,下一个符号*和int表明curErr是一个指向int类型的指针——结合起来curErr就是一个常量指针,指向不可变,但可通过其本身改变指向地址上的值。
指针pip同理,可以得知:pip是一个指向const double的const指针,指向和指向地址上的值不可变。

const* ———————————修饰指针
const int*——————const修饰指针指向的对象, int * const

就近原则

就近原则我们可以在K & R 《The C Programming Language》(2nd)

A.8.6.1 Pointer Declarators

In a declaration T D where D has the form

  • type-qualifier-listopt D1

and the type of the identifier in the declaration T D1 is
type-modifier T,'' the type of the identifier of D istype-modifier type-qualifier-list pointer to T.’’ Qualifiers
following * apply to pointer itself, rather than to the object to
which the pointer points.

const char **s;

对于以上的声明,以*号界定,开始读:
以最右边第一个 * 号开始,形式为:
const char ** | s
最右面第一个s前没有修饰符,可以改变指针指向;s是指向const char **的指针(const char *就是指针),因此s也就是指向指针的指针;
再看第二个* 号,形式为:
为const char * | *s
由于*s前没有修饰符,因此(*s)其值是可以改变的;

最后看const char *,类似于前面的const int *p1,因此表示该指针(***s)指向的(此处为字符串)为常量,其值不可改变;

测试:

	const char *fmt = "hello";
	const char **s = &fmt;
	*s++;				//正确,指向改变了
	(*s)++;				//正确,指向的地址上的值,可以改变值
	(**s)++;			//报错,指向的地址上的值不可改变
	**s++;

猜你喜欢

转载自blog.csdn.net/qq_43265890/article/details/83151110