设为首页 加入收藏

TOP

3.5.3 指针和数组(1)
2013-10-07 16:28:23 来源: 作者: 【 】 浏览:93
Tags:3.5.3 指针

3.5.3  指针和数组(1)

C++(www.cppentry.com)语言中,指针和数组有非常紧密的联系。就如即将介绍的,使用数组的时候编译器一般会把它转换成指针。

通常情况下,使用取地址符(参见2.3.2节,第52页)来获取指向某个对象的指针,取地址符可以用于任何对象。数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样,对数组的元素使用取地址符就能得到指向该元素的指针:
 

  1. string nums[] = {"one", "two", "three"}; // 数组的元素是string对象  
  2. string *p = &nums[0];                   // p指向nums的第一个元素 

然而,数组还有一个特性:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:
 

  1. string *p2 = nums; // 等价于p2 = &nums[0] 

在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。

由上可知,在一些情况下数组的操作实际上是指针的操作,这一结论有很多隐含的意思。其中一层意思是当使用数组作为一个auto(参见2.5.2节,第68页)变量的初始值时,推断得到的类型是指针而非数组:

  1. int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia是一个含有10个整数的数组  
  2. auto ia2(ia);   // ia2 是一个整型指针,指向ia的第一个元素  
  3. ia2 = 42;       // 错误:ia2是一个指针,不能用int值给指针赋值 

尽管ia是由10个整数构成的数组,但当使用ia作为初始值时,编译器实际执行的初始化过程类似于下面的形式:

  1. auto ia2(&ia[0]); //显然ia2的类型是int* 

必须指出的是,当使用decltype关键字(参见2.5.3节,第70页)时上述转换不会发生,decltype(ia)返回的类型是由10个整数构成的数组:
 

  1. // ia3是一个含有10个整数的数组  
  2. decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};  
  3. ia3 = p;    // 错误:不能用整型指针给数组赋值  
  4. ia3[4] = i; // 正确:把i的值赋给ia3的一个元素  

指针也是迭代器

与2.3.2节(第52页)介绍的内容相比,指向数组元素的指针拥有更多功能。vector和string的迭代器(第3.4节,106页)支持的运算,数组的指针全都支持。例如,允许使用递增运算符将指向数组元素的指针向前移动到下一个位置上:
 

  1. int arr[] = {0,1,2,3,4,5,6,7,8,9};  
  2. int *p = arr;   // p指向arr的第一个元素  
  3. ++p;            // p指向arr[1] 

就像使用迭代器遍历vector对象中的元素一样,使用指针也能遍历数组中的元素。当然,这样做的前提是先得获取到指向数组第一个元素的指针和指向数组尾元素的下一位置的指针。之前已经介绍过,通过数组名字或者数组中首元素的地址都能得到指向首元素的指针;不过获取尾后指针就要用到数组的另外一个特殊性质了。我们可以设法获取数组尾元素之后的那个并不存在的元素的地址:

  1. int *e = &arr[10]; //指向arr尾元素的下一位置的指针 

这里显然使用下标运算符索引了一个不存在的元素,arr有10个元素,尾元素所在位置的索引是9,接下来那个不存在的元素唯一的用处就是提供其地址用于初始化e。就像尾后迭代器(参见3.4.1节,第106页)一样,尾后指针也不指向具体的元素。因此,不能对尾后指针执行解引用或递增的操作。

利用上面得到的指针能重写之前的循环,令其输出arr的全部元素:

  1. for (int *b = arr; b != e; ++b)  
  2.     cout << *b << endl; // 输出arr的元素 

标准库函数begin和end

尽管能计算得到尾后指针,但这种用法极易出错。为了让指针的使用更简单、更安全,C++(www.cppentry.com)11新标准引入了两个名为begin和end的函数。这两个函数与容器中的两个同名成员(参见3.4.1节,第106页)功能类似,不过数组毕竟不是类类型,因此这两个函数不是成员函数。正确的使用形式是将数组作为它们的参数:
 

  1. int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia是一个含有10个整数的数组  
  2. int *beg = begin(ia);       // 指向ia首元素的指针  
  3. int *last = end(ia);        //指向arr尾元素的下一位置的指针 

begin函数返回指向ia首元素的指针,end函数返回指向ia尾元素下一位置的指针,这两个函数定义在iterator头文件中。

使用begin和end可以很容易地写出一个循环并处理数组中的元素。例如,假设arr是一个整型数组,下面的程序负责找到arr中的第一个负数:
 

  1. // pbeg指向arr的首元素,pend指向arr尾元素的下一位置  
  2. int *pbeg = begin(arr), *pend = end(arr);  
  3. // 寻找第一个负值元素,如果已经检查完全部元素则结束循环  
  4. while (pbeg != pend && *pbeg >= 0)  
  5.     ++pbeg; 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇3.5.2 访问数组元素 下一篇3.5.3 指针和数组(2)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: