指针: 指针是"指向"另外一种类型的复合类型。
与引用类似,指针也实现了对其他对象的间接访问。
指针与引用相比又有很多不同点:
1. 指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象
2. 指针无需在定义时赋初值。 和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
定义指针类型的方法: 将声明符写成 "*d" 的形式,其中d是变量名.
如果在一条语句中定义了几个指针变量,每个变量前面都必须有符号 "*"
eg:int *ip1, *ip2; //ip1和ip2都是指向int型对象的指针
double dp, *dp2; //dp2是指向double行对象的指针,dp是double型对象
获取对象的地址:
指针存放某个对象的地址,要想获取该地址,需要使用 "取地址符" (操作符&)
eg:int ival = 42;
int *p = &ival; //p存放变量ival的地址,或者说p是指向变量ival的指针。
其他所有指针的类型都要和它所指向的对象(对象类型)严格匹配
指针值:
指针的值(即地址)应属于下列4中状态之一:
1.指向一个对象
2.指向紧邻对象所占空间的下一个位置
3.空指针,意味着指针没有指向任何对象
4.无效指针,也就是上述情况之外的其他值
利用指针访问对象:
如果指针指向了一个对象,则允许使用 "解引用符"(操作符*)来访问该对象
eg:int ival = 42;
int *p = &ival; //p存放着变量ival的地址,或者说p是指向变量ival的指针
cout << *p; //由符号*得到指针p所指的对象,输出42
解引用操作仅适用于那些确实指向了某个对象的有效指针。
&和*不同意义:
eg: int i = 42;
int &r = 1; // &紧随类型名出现,因此是声明的一部分,r是一个引用
int *p; // *紧随类型名出现,因此是声明的一部分,p是一个指针
p = &i; // &出现在表达式中,是一个取地址符
*p = i; // *出现在表达式中,是一个解引用符
int &r2 = *p; // &是声明的一部分,*是一个解引用符
空指针(nullptr)
空指针不指向任何对象
eg: int *p1 = nullptr; //等价于int *p1 = 0;
int *p2 = 0; //直接将p2初始化为字面常量0
//需要首先#include cstdlib
int *p3 = null; //等价于int *p3 = 0;
赋值和指针
指针和引用都能提供对其他对象的间接访问
然而在具体实现细节上二者有很大的不同:其中最重要的一点就是引用本身并非对象。
一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象。
定义多个变量:
*仅仅是修饰了p而已,对申明语句中的其他变量。它并不产生任何作用:
eg: int* p1 , p2; //p1是指向int的指针,p2是int
涉及指针或引用的声明,一般有两种方法:
1.把修饰符和变量标识符写在一起,这种形式着重强调变量具有复合类型
eg: int *p1 , *p2; //p1和p2都是指向int的指针
2.把修饰符和类型名写在一起,并每条语句只定义一个变量,这种形式着重强调本次申明定义了一种复合类型
eg: int* p1; //p1是指向int的指针
int* p2; //p2是指向int的指针
指向指针的指针
通过*的个数可以区分指针的级别,也就是说,**表示指向指针的指针,***表示指向指针的指针的指针,以此类推。
eg: int ival = 1024;
int *pi = &ival; //pi指向一个int型的数
int **ppi = π //ppi指向一个int型的指针
指向指针的引用
引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用。
eg: int i = 42;
int *p; //p是一个int型指针
int *&r = p; //r是一个对指针p的引用
r = &i; //r引用了一个指针,因此给r赋值&i就是令p指向i
*r = 0; //解引用r得到i。也就是p指向的对象,将i的值改为0
与引用类似,指针也实现了对其他对象的间接访问。
指针与引用相比又有很多不同点:
1. 指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象
2. 指针无需在定义时赋初值。 和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
定义指针类型的方法: 将声明符写成 "*d" 的形式,其中d是变量名.
如果在一条语句中定义了几个指针变量,每个变量前面都必须有符号 "*"
eg:int *ip1, *ip2; //ip1和ip2都是指向int型对象的指针
double dp, *dp2; //dp2是指向double行对象的指针,dp是double型对象
获取对象的地址:
指针存放某个对象的地址,要想获取该地址,需要使用 "取地址符" (操作符&)
eg:int ival = 42;
int *p = &ival; //p存放变量ival的地址,或者说p是指向变量ival的指针。
其他所有指针的类型都要和它所指向的对象(对象类型)严格匹配
指针值:
指针的值(即地址)应属于下列4中状态之一:
1.指向一个对象
2.指向紧邻对象所占空间的下一个位置
3.空指针,意味着指针没有指向任何对象
4.无效指针,也就是上述情况之外的其他值
利用指针访问对象:
如果指针指向了一个对象,则允许使用 "解引用符"(操作符*)来访问该对象
eg:int ival = 42;
int *p = &ival; //p存放着变量ival的地址,或者说p是指向变量ival的指针
cout << *p; //由符号*得到指针p所指的对象,输出42
解引用操作仅适用于那些确实指向了某个对象的有效指针。
&和*不同意义:
eg: int i = 42;
int &r = 1; // &紧随类型名出现,因此是声明的一部分,r是一个引用
int *p; // *紧随类型名出现,因此是声明的一部分,p是一个指针
p = &i; // &出现在表达式中,是一个取地址符
*p = i; // *出现在表达式中,是一个解引用符
int &r2 = *p; // &是声明的一部分,*是一个解引用符
空指针(nullptr)
空指针不指向任何对象
eg: int *p1 = nullptr; //等价于int *p1 = 0;
int *p2 = 0; //直接将p2初始化为字面常量0
//需要首先#include cstdlib
int *p3 = null; //等价于int *p3 = 0;
赋值和指针
指针和引用都能提供对其他对象的间接访问
然而在具体实现细节上二者有很大的不同:其中最重要的一点就是引用本身并非对象。
一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象。
定义多个变量:
*仅仅是修饰了p而已,对申明语句中的其他变量。它并不产生任何作用:
eg: int* p1 , p2; //p1是指向int的指针,p2是int
涉及指针或引用的声明,一般有两种方法:
1.把修饰符和变量标识符写在一起,这种形式着重强调变量具有复合类型
eg: int *p1 , *p2; //p1和p2都是指向int的指针
2.把修饰符和类型名写在一起,并每条语句只定义一个变量,这种形式着重强调本次申明定义了一种复合类型
eg: int* p1; //p1是指向int的指针
int* p2; //p2是指向int的指针
指向指针的指针
通过*的个数可以区分指针的级别,也就是说,**表示指向指针的指针,***表示指向指针的指针的指针,以此类推。
eg: int ival = 1024;
int *pi = &ival; //pi指向一个int型的数
int **ppi = π //ppi指向一个int型的指针
指向指针的引用
引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用。
eg: int i = 42;
int *p; //p是一个int型指针
int *&r = p; //r是一个对指针p的引用
r = &i; //r引用了一个指针,因此给r赋值&i就是令p指向i
*r = 0; //解引用r得到i。也就是p指向的对象,将i的值改为0
注意: ******面对一条比较复杂的指针或引用的申明语句时,从右向左阅读有助于弄清楚它的真实含义。*****