(C++)指针(会一直跟新)

发表在    程序里的星辰与大海 09-05 07:51:46

5 1716 3

自己看书时的一些理解,可能有错误的地方。随着指针的使用增多,会不断修改这篇文章的内容,过去错误的会用划线划去后保留。

1.符号是有多重含义的,这一点书里提到过,但很容易在读代码时被忽略

#include 
//指针里符号的多重含义
int main()
{
	int i = 0;
	/*
	1.这里的*不是解引用符而是类型修饰符,因为这是一条声明语句,声明语句=基本类型+声明符列表,声明符列表指类型修饰符+变量名。
	2.类型修饰符的作用是指定了变量名是与基本类型相关的某种类型,所以我觉得这里更适合写int *p=&i,而不是int* p=&i,后者容易让人理解为int*是一种类型,当然这也没错。
	3.这句声明语句,相当于:
	  int *p;
	  p=&i;
	  所以,绝对绝对不能把声明语句和表达式中的符号一视同仁。
	*/
	int *p = &i;
	*(int*)p = 25;//因为类型不同,不能有*p=i这种操作,实在想赋值给指针,只能用强制类型转换
	return 0;
}

2.对引用、指针、常量引用、指向常量的指针、常量指针的理解

#include 
//对引用、指针、常量引用、指向常量的指针、常量指针的理解
int main()
{
	//引用
	int a = 1;
	int &r_a = a;//只要是引用都必须初始化
	r_a = 5;//引用不是一个对象,但可以通过改变引用来间接改变引用对象的值
	std::cout << "引用 " << a << std::endl;
	
	


	
	//指针
	int b = 1;
	/*
	*同一符号在不同语句中有不同的意义。
	*
	*声明语句中,*是类型修饰符,表达式中,*是解引用符。
	*
	*声明语句=基本类型+声明符列表=int *p,其表示定义一个名为p、指向int类型的指针。
	*
	*int *p=&b;实际上等价于:
	*int *p = nullptr;
	*p=&b;
	*如果想要给p赋int值,就要用上强制类型转换:
	*    *(int*)p=b;
	*/
	int *pb = &b;
	int **pib = &pb;
	int ***piib = &pib;//有3个*,表示pii是指向指针的指针的指针,最终指向的地址是&b
	std::cout << "多重指针的指针 " << ***piib << std::endl;

	
	
	






	//常量引用
	int c = 9;
	/*
	*const是一个限定符,其限定了不能对某个对象进行任何改变。不管是引用还是指针,只要对象是常量,声明中必须有const
	*
	*从右往左读,“&”表示r_c是一个引用,“int”说明了这是一个对int类型的引用,
	*“const”则说明这个引用是一个常量,即不能改变(这里的不能改变指的是引用绑定的对象不能变,不是值不能变)。
	*
	*c不能通过改变它的引用r_c而改变,但可以通过别的方式改变。
	*
	*r_c可以通过改变c来改变。
	*
	*常量引用有什么用呢?当我们需要对一个函数传入某个变量作为参数时,如果直接传要进行拷贝等工作浪费空间和时间,
	*此时如果传入那个变量的引用就可以省去那些操作(引用并没有申请存储空间,引用本身不是一个对象),而我们又怕
	*使用引用的时候不小心改变了那个变量,所以我们用了常量引用。
	*
	*如果这里的c是一个常量,则c、r_c都不能改;
	*/
	const int &r_c = c;
	c = 10;
	std::cout << "常量引用 " << c << " " << r_c << std::endl;
    
	
	double d = 3.14;
	/*
	*引用的类型必须与其引用对象的类型一致,但有两个例外,其中之一就是在常量引用的初始化时,可以类型不一致,
	*实际上它的执行是通过一个临时量来使其合法的:
	*double d = 3.14;
	*const int tem = d;
	*const int &r_d = tem;
	*在这里,无法通过改变d值来改变r_d(改变tem才行,但是tem是编译器为了类型转换而临时出现的,并不是一个真的对象)。
	*需要说明的是,这种转换必须是可以互相转换的类型(double和int是可以互相转换的)
	*
	*不能用一个非常量引用来引用一个常量,即下面的语句是非法的:
	*const int d = 3;
	*int &r_d = d;
	*/
	const int &r_d = d;
	d = 8.5;
	std::cout << "常量引用类型不一致 " << d << " " << r_d << std::endl;







	//指向常量的指针
	const int e = 9;
	/*
	*从右往左看,“*pe”表示一个名为pe的指针,“int”表示这个指针指向int类型,“const”表示这个指针指向的是一个常量。
	*
	*指向常量的指针,只是说明不能通过改变指针来改变指向的对象,并没有说指针本身的值不能改变。
	*
	*指针的类型必须与其所指对象的类型一样,但是有两个例外,其中一个就是指向常量的指针,指向的对象不一定非得是常量。
	*
	*e是常量,则pr声明处的const不可省略,因为必须强调指向的是一个常量才能存e这个常量的地址;如果e不是常量,pe声明处的const意在
	*指出不能通过pe指针来改变指针指向的对象,不管这个对象是不是常量——如果不是常量,可以通过除指针外的方式改变对象。
	*书上一句话可以很好的概括这一点:所谓指向常量的指针或引用,不过是指针或引用“自以为是”罢了,它们觉得自己指向了常量,所以自觉的不去改变所指对象的值。
	*
	*指针和引用不一样,有关指针的初始化并没有类似引用中的tem这个中间值的执行步骤——即如果基本类型不一样是不能初始化的,只是说常量和非常量都可以初始化。
	*也就是说,不要过度的类比指针和引用的操作,两者相同点没有那么多,比如这里的pe即使是自己和指向的对象都加了const,pe还是可以改变。
	*/
	const int *pe = &e;
	const int f = 10;
	pe = &f;
	std::cout << "指向常量的指针 " << *pe << std::endl;





	//常量指针
	int g = 10;
	/*
	*从右往左看,“const”表示pg是一个常量,“*”表示pg是一个常量指针,“int”表示pg指向一个int对象
	*
	*常量指针必须初始化。
	*
	*常量指针不能改变(指向的地址不变),只能改变解引用后的值,即只能改变g值。
	*/
	int *const pg = &g;
	g = 9;
	std::cout << "常量指针指向非常量 " << *pg << std::endl;

	/*
	*一样的同上从右往左看,我们发现在指针的声明中,限定符const在声明列表里则是限定列表里指针,在基本类型处则是限定指针指向的对象,
	*这里的ph表示一个常量指针指向一个int的常量h。由于都是常量,所以都不能改变。
	*/
	const int h = 4;
	const int *const ph = &h;
	std::cout << "常量指针指向常量 " <<*ph << std::endl;
	return 0;
}

3.类型不同,读取的方式也是不一样的,之所以要求类型一致就是这个原因,同一串二进制,用int去读和用double去读读出来的结果是不一样的。引用实际上是一个存储地址存了两个名字,一个是引用名,一个是对象名。



登录或注册后发布评论