vector的遍历可使用洗标或迭代器实现,同理也可用下标或指针来遍历数组。指针是指向某种类型对象的符合数据类型,是用于数组的迭代器:指向数据中的一个元素,在指向数据元素的指针上使用接引用操作符“*”和自增操作符“++”,与在迭代器上的用法类似。对指针进行解引用操作,可获得该指针所指对象的值。而当指针做自增操作时,则移动指针使其指向数组中的下一个元素。在使用指针编写程序之前,我们需进一步了解他。
1.指针的定义
指针通常比较难理解对于初学者,由指针错误引起的调试问题连富有经验的程序员都感到头疼。然而,指针式大多数C程序的重要部分,而且在许多C++程序中仍然受到重用。
指针的概念很简单:指针用于指向对象。与迭代器一样,指针提供对齐所指对象的简介访问。知识指针结构更通用一些。与迭代器不同的是,指针用于指向单个对象,而迭代器只能用于访问容器内的元素。
具体来说,指针保存的是另一个对象地址:
string s("hello world");
string *sp = &s; //sp持有s的地址
第二条语句定义了一个指向string类型的指针sp,并初始化sp使其指向string类型的对象s。*sp中的*操作符表面sp是一个指针变量,&s中的&符合是取地址操作符,当次操作符用于一个对象上市,返回的该对象的存储地址。取地址操作符只能用于左值。因为只有当变量用作左值是,才能取其地址。同样地,由于用于vector类型,string类型或内置数组的下标操作和解引用操作生策划那个左值,因此可对这两种操作的结果做取地址操作,这样皆可获取某一特定对象的存储地址。
2.指针的定义和初始化
每个指针都有一个与之关联的数据类型,该数据类型决定了指针所指向的对象的类型。例如,一个int类型指针只能指向int类型对象。
(1)指针变量的定义
C++语言使用*符好把一个标识符声明为指针:
vector<int> *pvec; //pvec指向vector<int>的指针
int *ip1, *ip2; //ip和ip2指向int的指针
string *pstring; //pstring指向string的指针
double *dp; //dp指向double的指针
建议:理解指针声明语句是,从右向左阅读
从右向左阅读pstring变量的定义,可以看到 string *pstring;语句吧pstring定义为一个指向string类型对象的指针变量。类似地,语句
int *ip1, *ip2把ip1和ip2都定义为指向int型对象的指针。
在声明语句中,符号*可用在制定类型的对象类表的任何位置:
(2)另一种声明指针的风格
在定义指针变量时,可用空格将符号*与其后的标识符分割开来。下面的写法是正确的
string* ps;
也就是说,该语句把ps定义为一个指向string类型对象的指针。
这种指针声明风格容易引起这样的误解:把string*理解为一种数据类型,认为在同一声明语句中定义的其他变量也是指向string类型对象的指针。然而
string* ps1,ps2;
实际上只把ps1定义为指针,必须在灭个变量标识符前面加符号*声明:
string* ps1, *ps2;
(3)连续声明多个指针容易引起混淆
有两种格式,一种格式为:
string* ps1;
string* ps2;
另一种为:
string* ps1, *ps2;
(4)指针的可能取值
一个有效的指针必然是以下三种状态之一:保存一个特定对象的地址;指向某个对象后面的另一个对象;或者是0值。若指针保存0,表明他不指向任何对象。未初始化的指针式无效的。下列定义都是正确的。
int ival = 1024;
int *pi = 0;
int *ip2 = &ival;
int *pi3;
pi = pi2;
pi2 = 0;
(5)避免使用未初始化的指针
就像使用其他没有初始化的变量一样,实用未初始化的指针的行为是没有定义如何操作的,他几乎总会导致运行时崩溃。然而,导致崩溃的这一原因很难发现。
(6)指针的初始化和赋值操作的约束
对指针进行的初始化或复制只能使用以下四种类型的值:
1、0值常量表达式,例如,在编译时可获得0值的整型const对象或字面值常量0.
2、类型匹配的对象地址。
3、另一对象之后的狭义地址。
4、同类型的另一个有效指针。
把int行变量付给指针是非法的,尽管此int型变量的值可能是0。但允许吧数值0或在编译时可获得0值的const量赋给指针:
int ival;
int zero = 0;
const int c_ival = 0;
int *pi = ival; //错误:
pi = zero; //错误:
pi = c_ival; //正确:
pi = 0; //正确:
除了使用0还可以使用NULL赋值 int *pi = NULL;