📌 来自C++ primer中的6.2.4部分
数组的特性
- 数组名称作为指向其中第一个元素的pointer;
- 数组不能被copy
int a[] = {1, 2, 3}; int b[3] = a; // 错误,不能用一个数组初始化另一个数据 b = a; // 错误,不能数组赋值和copy
📌 有些编译器允许数组赋值,但是这种是作为compiler extension存在的,不是标准支持的语法,跨编译器时可能会存在问题。
数组作为函数参数
基于数组的特性,不能复制,因此无法使用数组作为函数的形参,也就不能按值传递数组;但是,可以利用另一个特性,向函数传递数组名称作为第一个元素的指针。
声明数组作为函数参数
// 三种声明等价,忽略它们定义的样子
void print(const int * );
void print(const int[]);
void print(const int[10]);
上述三种方式中,函数的参数均为const int*
. 因此,当函数调用时,判断传入的参数时,只会按照这个类型进行匹配。
int i = 0;
int j[2] = {0, 1};
print(&i); // ok, int *类型,可以传入
print(j); // ok, 数组的维度不相关
这里,数组的维度即使不匹配也没问题,因为不影响。
但是,因此函数也不知道数组的大小了,为了进行遍历,需要一些额外的方法,共有3种。
依赖数组中的变量类型存在标识符
典型的就是C风格的字符串,结尾有“\0” null charactor. 因此,可以根据这个判断是否到结尾,如下:
void print(const char *cp) {
if (cp){
while ( *cp){
cout << *cp++;
}
}
}
这种方法对于字符串等类型友好,但是不适用于如int等类型的数据,因为没有结尾标识符。
传递数组的收尾指针
void print(const int * beg, const int * end) {
while (beg != end){
cout << *beg << endl;
beg++;
}
}
int j[2] = {0, 1};
print(begin(j), end(j));
其中:
- begin返回第一个元素的指针;
- end返回最后一个元素之后的指针,注意,这个指针指向的元素不在数组中,但是是有效的指针value;
这种方法,通用,安全,不受类型的限制。
显式传递数组长度
void print(const int ia[], size_t size) {
for (size_t i = 0; i != size; ++i) {
cout << ia[i] << endl;
}
}
int j[] = { 0, 1 };
print(j, end(j) - begin(j));
这种方法也是安全的,但是要保证size与ia的长度是一致的。
一些注意事项
- 上述函数的定义中,参数均为 pointer to const;
When a function does not need write access to the array elements, the array parameter should be a pointer to const. A parameter should be a plain pointer to a nonconst type only if the function needs to change element values.
- reference对于数组参数的影响 对于一个数组变量,可以定义它的reference, 对于函数参数中数组,也可以定义数组的reference,但是会有一点迷惑。
对第一个来说,因为数组的维度是数组类型的一部分,当调用函数void print(int (&arr)[10]) { for (auto elem : arr) cout << elem << endl; } // 1. arr[10] stores ten reference to ints. f(int &arr[10]) // 2. 表示,arr is a reference to an array of ten ints, (&arr)中括号必须存在 f(int (&arr)[10])
print(int (&arr)[10])
时,必须保证维度相同。int i = 0, j[2] = {0, 1}; int k[10] = {0,1,2,3,4,5,6,7,8,9}; print(&i); // error: argument is not an array of ten ints print(j); // error: argument is not an array of ten ints print(k); // ok: argument is an array of ten ints