在函数中以数组作为形参的方法

本文介绍了三种在函数中以数组作为形参时的处理方法,重点介绍C++11标准是如何管理数组大小的。

数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响,这两个性质分别是:
不允许拷贝数组以及使用数组时通常会将其转换成指针。因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。

尽管不能以值传递的形式传递数组,但是我们可以把形参写成类似数组的形式:

//尽管形式不同,但这三个print函数是等价的
//每个函数都有一个const int*类型的形参
void print(const int*);
void print(const int[]);
void print(const int[10])//这里的维度表示我们期望数组含有多少元素,实际不一定

当编译器处理对print函数的调用时,只检查传入的参数是否是const int*类型:

int i = 2;
int j[2] = {1,2};
print(&i);  //正确,&i的类型是int*
print(j);   //正确,j被转换成int*并指向j[0]

如果我们传给print函数的是一个数组,则实参自动地转换成指向首元素的指针,数组的大小对函数的调用没有影响。

由于数组实际上是以指针的形式传递给函数的,因此一开始函数并不知道数组的确切尺寸,调用者应该为此提供额外的一些信息。管理指针形参有三种常用的技术:

使用标记指定数组长度

这种方法要求数组本身包含一个结束标记,使用这种方法的典型示例是C风格字符串。C风格字符串存储在字符数组中,并且在最后一个字符后面跟着一个空字符。函数在处理C风格字符串时遇到空字符就停止:

void print(const char *cp)
{
    if(cp){     //若cp不是空指针
        while(*cp){     //只要指针所指字符不是空字符
            cout<<*cp++;    //输出当前字符并将指针前移
        }
    }
}

这个方法适用于那些有明显结束标记且该标记不会与普通数据混淆的情况。

显示传递一个表示数组大小的形参

这种方法是专门定义一个表示数组大小的形参,在C程序和过去的C++程序中常常使用这种方法。

//const int ia[]等价于const int *ia
//size表示数组的大小,将它显示地传给函数用于控制对ia元素的访问
void print(const int ia[],size_t size)
{
    for(size_t i = 0; i != size; ++i){
        cout<<ia[i]<<" ";
    }
}

这种方法通过形参size的值确定要输出多少个元素,调用print函数时必须传入这个表示数组大小的值:

int j[] = {1,2,3};

print(j,3);

使用标准库函数begin和end

C++11标准引入两个名为begin和end的函数,begin函数返回指向数组首元素的指针,end函数返回指向数组尾元素下一位置的指针,这两个函数定义在iterator头文件中。
示例代码如下:

#include<iostream>
using namespace std;
int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,-1,5,3,4};

    int *pbeg = begin(arr);     //指向arr首元素的指针
    int *pend = end(arr);       //指向arr尾元素的指针

    //寻找第一个负值元素,如果已经检查完全部元素则结束循环
    while(pbeg != pend && *pbeg >= 0){
        ++pbeg;
    }
    cout<<*pbeg<<endl;  //输出第一个负数的值
}

对于本文的print函数,可以写成如下形式:

void print(const int *beg, const int *end)
{
    //输出beg到end之间(不含end)的所有元素
    while(beg != end)
        cout<<*beg++<<" ";
}

为了调用这两个函数,我们需要传入两个指针:一个指向要输出的首元素,另一个指向尾元素的下一个位置。使用方法如下:

int a[] = {1,2,3};

print(begin(j),end(j));
posted @ 2016-07-28 15:02  larryking  阅读(32401)  评论(0编辑  收藏  举报