14 February 2017
是除 引用 之外的一种符合类型,指针实现了对其他对象的间接访问,然而指针与引用相比又有很多不同点,其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象,其二,指针无须再定义时赋予初值,和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
定义指针类型的方法将声明符号写成 *d 的形式。
获取对象地址使用 (&)
int ival = 42;
int *p = &ival;
那么引用即可以绑定到指针上
int li = 52;
int &val = li;
&val = *p;
在使用指针的时候,带*则是表示对象取值,获取到了对象存储区域的首地址,不带 * 则是表示获取的首地址。
利用指针访问对象
int ival = 42;
int *p = &ival;
std::cout << *p << std::endl;
符号的多重含义
&和*这样的符号,既能作用为表达式中的运算符,也能作为声明的一部分出现,符号的上下文决定了符号的意义。
int i = 42;
int &r = i;//&紧随类型名的出现,因此是声明的一部分,r是一个引用
int *p;//*紧随类型名的出现,因此是声明的一部分,p是一个指针
p = &i;//出现在表达式中,是一个取地址符
*p = i;//*出现在表达式中,是一个解引用符
int &r2 = *p;//&是声明的一部分,*是一个解引用符
空指针
不指向任何对象,在试图使用一个指针之前代码可以首先检查它是否为空。
指针和引用都能提供对其他对象的间接访问,然而在具体实现细节上二者有很大的不同,其中最重要的一点就是引用本身并非一个对象,一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象。
指针
和它存放的地址之间就没有这种限制了,和其他的任何变量一样,给指针赋值就是令它存放一个新的地址,从而指向一个新的对象。
int i = 42;
int *pi = 0;//pi被初始化,但没有指向任何对象
int *pi2 = &i;//pi2被初始化,存有i的地址
int *pi3; //如果pi3定义于块内,则pi3的值是无法确定的
pi3 = pi2; // pi3 和 pi2 指向同一个对象i
pi2 = 0; //现在pi2不指向任何对象了
有时候想要搞清楚一条赋值语句到底是改变了指针的值还是改变了指针所指向对象的值不容易,最好的办法就是记住赋值永远改变的是等号左侧的对象
pi = &ival; //pi的值被改变,现在pi指向了ival
相反的
*pi = 0; //ival的值被改变了,指针pi并没有发生改变
*pi指向的那个对象发生了改变
注:不同数据类型的指针和对象不能进行赋值。
只要指针拥有一个合法的值。
int ival = 1024;
int *pi = 0; // pi 合法,是一个空指针
int *pi2 = &ival; //pi2是一个合法的指针,存放着ival的地址
if(pi) //pi的值是0,因此条件的值是false
//
if(pi2) //pi2指向ival,因此它的值不是0,条件的值是true
任何非0指针对应的条件值都是true
void*指针是一种特殊的指针类型,用于存放任意对象的地址。一个 void * 指针存放着一个地址。不同的是该地址中到底是什么类型的对象不了解。
double obj = 3.14, *pd = &obj; //正确 void*能存放任意类型对象的地址
void *pv = &obj; //obj可以是任意类型的对象
pv = pd; //pv可以存放任意类型的指针
不能判断指针是否指向了一个合法的对象。所以指针最好进行初始化
最为头疼的一节
int ival = 1024;
int *pi = &ival; //pi指向一个int型的数
int **ppi = π //ppi指向一个int型的指针
ppi—>pi—>ival(1024)
解引用int型指针会得到一个int型的数,解引用指向指针的指针会得到一个指针
int ival = 1024;
int *pi = &ival;
int **ppi = π
std::cout << *pi << std::endl <<
*ppi << std::endl;
output:
1024
0x7fff5fbff7ac
Program ended with exit code: 0
引用本身不是一个对象,因此不能定义指向引用的指针。
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
注:r到底是什么类型。最简单的方法是从右向左阅读r的定义,离变量名最近的符号对变量的类型有最直接的影响,因此r是一个引用。
— Kong Jing