随便记记balabala

const的引用

通常情况下:引用的类型都要与之绑定的对象类型严格匹配

int a = 100;

int &val = a;

但是常量的引用不需要。

	double i = 14.42;
	const int& i0 = i;
	cout << i0;

最后的输出是14;

也就是说,常量的引用会对引用的类型不匹配的对象会进行类型的转换。

此处的i0引用了一个int类型的对象,但是i是双精度浮点数。因此为了确保让i0绑定了一个整数,编译器把上述代码变成了如下形式:

const int temp = i; //用变量实现类型转换
const int &i0 = temp; //再用i0对临时量(此时的类型是匹配的)进行绑定

就很奈斯。

另外,此时常量引用,其实严格意义上貌似不是一个常量,虽然但是,我们仍然无法直接对const 对象的引用,进行赋值,或者其他试图更改常量的操作。但是,可以通过其他方式改变常量的值

#include<iostream>
using namespace std;

int main() {
	
	int val = 100;
	const int &cval = val;
	cout << cval << endl;
	int& ival = val;
	++ival;
	cout << cval;



}

输出结果是

100 
101

或者直接对原始对象 val进行赋值,也会改变const对象的引用的值。

补充:通常情况下,引用是不可以用字面值进行赋值的,但是常量引用是可以的

const int &val = 42;
cout << val;

结果是42

也就是说,不能通过常量引用去改变对象,那么绑定的是字面值还是对象都无所谓了,反正都不能做改变也就不存在改变无意义的情况。 

指针和const

	const double pi = 3.14;//初始化双精度常量pi
	const double* cptr = &pi;//只能使用指向常量的指针存放常量对象的地址
	double a = 100;
	cptr = &a;
	cout << *cptr; //输出100;
	++ *cptr;//不能给常量赋值

指针的类型必须和他所指的对象的类型一致。但是有两个例外,第一种例外就是允许一个指向常量的指针指向非常量对象。

再看上面的代码,我们发现,指向常量的指针,仅仅要求不能通过该指针改变对象的值,我们甚至可以直接改变指针的指向,指向一个非常量的对象,二者并没有绑定的关系

 这是我自己画的图,我自己的理解,不知道有没有错误,const常量的地址必须存放在const *类型中,但是const *也可以存放非常量的地址。但是无论存放的是谁的地址,都不能通过解引用符“*”,对 对象进行更改。和const引用一样,虽然不能直接通过指针对 对象进行更改,但是其他途径更改对象,无所谓。

这里的const只是在说:这个指针指向的是一个常量,不能通过这个指针乱改这个常量。和接下来要说的const指针大不相同。

书中:所谓指向常量的指针或引用,不过是指针或引用“自以为是”罢了,他们自己觉得自己指向了常量,所以自觉地不去改变所指对象的值。

const指针

其实上面,我们的重点是在类型上。所以我们可以改变指针的指向。下面要说的const指针,是把指针本身定为常量。常量指针和常量一样,必须初始化,并且初始化完成后,存放在指针中的地址就不能再被改变了。

#include<iostream>
using namespace std;

int main() {
	

	int val = 100;
	int* const cptr = &val; //把*放在关键字之前说明指针是一个常量
							//这样的书写形式隐含着一层意味
							//即不变的是指针本身的值(指向的对象的地址)
							//而不是指向的对象
							//指向的对象是可以通过解引用符修改值的。
	const double pi = 3.14;
	//这里第一个const保证了不能通过指针修改这个常量
	//第二个const保证了,这个指针存放的地址,已经和这个指针绑定,不能更改。
	const double* const pip = &pi;
	//pip = &val; 不合法,因为pip是一个常量指针,被初始化后,就不能更改值
	//*pip = 1111; 不合法,它指向的是一个双精度常量,不能通过该指针修改,他所指向的对象的值。

	int* const cptr1 = &val;
	*cptr1 = 100;
	cout << *cptr1;//输出100,这里的类型int
				   //表示解引用后得到的是一个int类型的变量,可以更改值
				   //如果是const int ,则不能修改值


	

}

我感觉这种定义语句,从右向左看,是一个不错的选择。

顶层const

如前所述,指针本身是一个对象,它又可以指向另外一个对象。因此指针本身是常量,以及指针所指的是不是一个常量是两个相互独立的问题。

底层const:表示指向的对象是一个常量,与指针和引用等复合类型相关。

顶层const:表示指针本身是一个常量,顶层const可以表示任意的对象是常量,对任意数据类型都适用。

比较特殊的是:指针既可以是底层const,又可以是顶层const


	int const a = 100;
	cout << a;
//我发现不止指针可以在类型后面使用const,其他的数据类型也可以。

用于声明引用的const都是底层const,对常量对象取地址也是const

const int ci =100;
&ci:底层const


 


	int const a = 100;
	int b = a;
	const int* c = &a;//顶层const可以给底层const初始化。
	//int* const d = c;//底层const不能给顶层const初始化(拷贝),因为因为c本身是底层const,它本身是一个变量
					 //但是d是顶层const,一个常量。所以变量不可以给一个常量进行拷贝。


	//再来一个例子,引用的例子
	const int& bval = b;//引用都是底层const
	const int* const p = &bval;
	//int* const p2 = &bval; p2是一个顶层const,但是bval是一个底层const,不能执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值