数组形参

数组的两个特殊性质:

  • 不允许拷贝数组
  • 使用数组时会将其转换成指针

因为不能拷贝数组,所以无法以值传递的方式使用数组参数。

因为数组会被转换成指针,所以为函数传递一个数组时,实际上传递的是指向数组首元素的指针。

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

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

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

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

使用标记指定数组长度

数组本身包含一个结束标记,函数在处理C风格字符串时遇到到空字符串停止:

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

这种方法适用于有明显结束标记且该标记不会与普通数据混淆的情况,但是对于像 int 这样所取值都是合法值的数据就不太有效了。

使用标准库规范

void print(const int* beg, const int* end)
{
    //输出beg到end之间的所有元素
    while (beg != end)
        cout << *beg++ << endl;//输出当前元素并将指针向前移动一个位置
}

传入两个指针:一个指向要输出的首元素,另一个指向尾元素的下一位置:

    int j[2] = { 0,1 };
    //j转换成指向它首元素的指针
    //第二个实参是指向j的尾后元素的指针
    print(begin(j), end(j));//begin和end函数

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

专门定义一个表示数组大小的形参,将 print 函数重写成如下形式:

//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] << endl;
    }
}

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

    int j[] = { 0,1 };//大小为2的整型数组
    print(j, end(j) - begin(j));

传递给函数的 size 值不超过数组实际大小,函数就是安全的。

数组形参的const

  • 当函数不需要对数组元素执行写操作的时候,数组形参应该是指向 const 的指针。
  • 只有当函数确实需要改变元素值的时候,才把形参定义成指向非常量的指针。

数组引用形参

C++语言允许将变量定义成数组的引用,形参也可以是数组的引用。引用形参绑定到对应的实参上,也就是绑定到数组上:

//正确:形参式数组的引用,维度式类型的一部分
void print(int(&arr)[10])
{
    for (auto elem:arr)
    {
        cout << elem << endl;
    }
}

Note:

&arr 两端的括号必不可少

f(int &arr[10])    //错误:将arr声明成了引用
f(int (arr)[10])   //正确:arr是具有10个整数的整型数组的引用

因为数组的大小是构成数组类型的一部分,所以只要不超过维度,在函数体内就可以放心地使用数组。但是,这一用法无形中限制了 print 函数的可用性,只能将函数作用于大小为10的数组:

    int i = 0, j[2] = {0,1};
    int k[10] = {0,1,2,3,4,5,6,7,8,9};
    print(&i);//错误:实参不是含有10个整数的数组
    print(j);//错误:实参不是含有10个整数的数组
    print(k);//正确:实参是含有10个整数的数组

传递多维数组

和所有的数组一样,当将多维数组传递给函数时,真正传递的是指向数组首元素的指针。因为我们处理的是数组的数组,所以数组首元素本身就是一个数组,指针就是一个指向数组的指针。

数组的第二维的大小都是数组类型的一部分,不能省略:

//matrix指向数组的首元素,该数组的元素由10个整数构成的数组
void print(int(*matrix)[10], int rowSize) {/*...*/}

上述语句将matrix声明成指向含有10个整数的数组的指针。

Note:

*matrix两端的括号必不可少:
int    *matrix[10];        //10个指针构成的数组
int    (*matrix)[10];     //指向含有10个整数的数组的指针

使用数组的语法定义函数,编译器会忽略掉第一维度,不要把它包含在形参列表内:

//等价定义
void print(int matrix[][10], int rowSize) {}

matrix 的声明看起来是一个二维数组,实际上形参是指向含有10个整数的数组的指针。

posted @ 2019-07-08 13:29  CodeWithMe  阅读(619)  评论(0)    收藏  举报