2.3 复合类型

复合类型是指基于其他类型定义的类型。eg:引用 指针

一条声明语句由一个基本数据类型和一个紧随其后的一个声明符列表组成。每个声明符命名了一个变量并指定该变量为与基本数据类型有关的某种类型。

2.3.1 引用

引用通常指左值引用。

引用为对象起了另外一个名字,引用类型引用另外一种类型。通过将声明符写成&d的形式来定义引用类型,d是声明的变量名。

int ival = 1024;
int &refVal = ival;
int &refVal2;           //报错,引用必须被初始化

refVal = 2; //把2赋值给refVal指向的对象,即ival
int ii = refVal; //等同于ii = ival

int &refVal3 = refVal; //正确,绑定到ival
int i = refVal; //利用与refVal绑定的对象的值初始化i

引用本身不是一个对象,所以不能定义引用的引用。

int &refVal4 = 10;                //错 引用类型的初始值必须是一个对象
double dval = 3.14;
int &refVal5 = dval;             //错  此处引用类型的初始值必须是int型对象

 

 

2.3.2  指针

指针是指向另外一种类型的复合类型。

与引用的异同:

都实现了对其他对象的间接访问。

不同点:1.指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。

           2.指针无需在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

int ival = 42;
int *p = &ival;      //p存放变量ival的地址,或者说p是指向变量ival的指针

由于引用不是对象,没有实际地址,所以不能定义指向引用的指针。

double dval;
double *pd = &dval;    
double *pd2 = pd;      

int *pi = pd;               //错误。指针pi的类型和pd的类型不匹配
pi = &dval;                 //错误。试图把double型对象的地址赋給int型指针

指针值

指针的值(既地址)应属于下列4种状态之一:

  1. 指向一个对象。
  2. 指向紧邻对象所占空间的下一个位置。
  3. 空指针,意味着指针没有指向任何对象。
  4. 无效指针。

利用指针访问对象

int ival;
int *p = &ival;
cout<< *p;       //由解引用符号*得到指针p所指的对象,输出42


//对指针解引用会得出所指的对象,因此如果给解引用的结果赋值,实际上也就是给指针所指的对象赋值

*p = 0//经由p为变量ival赋值
cout<<*p;       //输出0

解引用操作仅适用于那些确实指向了某个对象的有效指针。

//像&和*,既能用作表达式里的运算符,也能作为声明的一部分出现,符号的上下文决定符号的意义

int i = 42;
int &r = i;
int *p;
p = &i;
*p = i;
int &r2 = *p;
//紧随类型名出现,是声明的一部分,组成复合类型,出现在表达式中,是运算符

空指针

int *p1 = nullptr;               //等价于int *p1 = 0;
int *p2 = 0;                      //直接将p2初始化为字面常量0
//首先需要#include cstdlib
int *p3= NULL;

把int变量直接赋給指针是错误的操作,即使int变量的值恰好等于0

int zero = 0;

pi = zero;        //错误

 

建议初始化所有指针 ,并且尽量等定义了对象之后再定义指向它的指针。如果实在不知指针指向何处,就把它初始化为nullptr或者0

赋值和指针

赋值永远改变的都是等号左侧的对象

int i = 42;
int *pi = 0;        
int *pi2 = &i;
int *pi3; 

pi3 = pi2;
pi2 = 0;
pi =  &ival;               //pi的值被改变,现在pi指向ival

*pi = 0;                   //ival的值被改变,指针pi并没有改变,*pi改变,即指针指向的对象发生改变

void* 指针

 可存放任意对象的地址。

double obj = 3.14 , *pd = &obj;
void *pv = &obj;
pv = pd;

void* 指针能做的事比较有限:与别的指针比较,作为函数的输入或输出,赋給另一个void*指针。

不能直接操作void*指针所指的对象。

复合类型的声明

int ival = 1024;
int *pi = &ival;      //pi指向int型的数
int **ppi = &pi;    //ppi指向int型的指针

//ival=*pi=**ppi

int i=42;
int *p;
int *&r = p;          //r是一个对指针p的引用

r = &i;                 //r引用了一个指针,因此给r赋值&i就是令p指向i
*r = 0;                //解引用r得到i,也就是p指向的对象,将i的值改为0

引用本身不是一个对象,不能定义指向引用的指针。但指针是对象,可以定义对指针的引用。

面对一条较复杂的指针或引用的声明语句,从右向左读。离变量名最近的符号对变量的类型有最直接的影响。

 

posted @ 2017-05-12 10:06  1ww3  阅读(244)  评论(0)    收藏  举报