C++复合类型(2)

C++复合类型(2)

指针

什么是指针

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。

指针是“指向(point to)”另外一种类型的复合类型。与引用相似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。其一:指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。其二:指针无需再定义时赋值。和其他内置类型一样,在块作用域中定义的指针如果没有被初始化,也将拥有一个不确定的值。

指针的声明与定义

定义指针类型的方法可以将声明符写成 * d 的形式,其中 d 是变量名。如果在一条语句中定义了多个指针变量,每个变量前面都必须有符号 * 。

指针变量声明的一般形式:

引用类型名 * 指针变量名;

type *var-name;

在这里,type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。
以下是有效的指针声明:

int    *ip1, *ip2;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

指针获取对象的地址

指针用来存放某个对象的地址,要想获取该地址,需要使用取地址运算符(操作符 &):
例如:

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

注意: 不能定义指向引用的指针 因为:引用不是对象,没有实际地址。

指针的类型要与其所指的对象类型严格匹配:

double dval;
double *pd = & dval;     // 正确:初始值是 double 型对象的地址
double *pd2 = pd;        // 正确:初始值是指向 double 对象的指针

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

因此在生命语句中指针的类型实际上被用来指定它所指向对象的类型,所以二者必须匹配。如果指针指向了一个其他类型的对象,对该对象的操作将发生错误。

指针值

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

  1. 指向一个对象
  2. 指向紧邻对象所占空间的下一个位置
  3. 控指针,意味着指针没有指向任何对象
  4. 无效指针,也就是上述情况之外的其他值
    试图拷贝或以其他方式访问无效指针的值豆浆引发错误。编译器并不负者检查此类错误,这一点和试图使用未经初始化的变量是一样的。访问无效指针的后果无法预计,因此程序员必须清楚任意给定的指针是否有效。

利用指针访问对象

如果指针指向了对象,则允许使用解引用符(操作符 *)来访问对象:

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

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

*p = 0;          // 有符号* 得到指针所指的对象,即可经由p 为变量ival 赋值
cout << *p;      // 输出 0

如上所示:为 *p 赋值实际上是为 p 所指对象赋值。

空指针

空指针(null pointer)不指向任何对象,在试图使用一个指针之前代码可以首先检测它是否为空。一下列出几个生成空指针的方法:

int *p1 = nullptr;     // 等价于*p1 = 0;
int *p2 = 0;           // 直接将 p2 初始化为字面常量0;
int *p3 = NULL;        // 等价于*p3 = 0;

得到空指针最直接的办法就是用字面值nullptr来初始化指针,这也是C++11中新标准刚刚引入的一种方法。nullptr是一种特殊类型的字面值,它可以被转化成任意的指针类型。另一种方法就如对 p2 的定义一样,也可以通过将指针初始化为字面值 0 来生成空指针。

指针和引用

指针和引用都能提供对其他对象的间接访问,然而再具体实现细节上二者有很大不同,其中最重要的一点引用本身并非一个对象。一旦定义了引用,就无法令其在绑定其他对象,之后每次使用这个引用都是访问它最初绑定的那个对象。
指针和它存放的地址之间就没有这个限制。和其他任何变量一样,给指针赋值就是令它存放一个新地址,从而指向一个新对象。

void * 指针

void *是一种特殊的指针类型,可用于存放任意对象的地址。一个void *指针存放着一个地址,这一点和其他类型的指针类似。不同的是,我们对该地址中到底存放的是什么类型的对象并不了解。

double obj = 3.14, *pd = & obj;
void *pv = & obj;     // obj 可以使任意类型的对象
pv = pd;              // pv可以存放任意类型的指针

概括来说,以void * 的视角来看内存空间也就仅限于内存空间,没有办法访问内存空间中所存的对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值