一、基本数组
1、数组的特点
- 数组中每个元素数据类型相同。
- 数组中元素的位置在内存中是连续的。
- 在很多情况下使用数组的名字,其实使用的是一个指向数组首元素的指针。
2、数组作为函数的形参
(1)、数组有两个性质:不允许拷贝数组,以及使用数组时会将其转换成指针。因为不能拷贝数组,所以无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
(2)、数组的引用
// arr是一个整型数组的引用,该数组具有10个整数
void f1(int (&arr)[10]);
(3)、指针和数组
// 10个指针构成的数组,数组的元素类型是指针:int *
int *arr1[10];
// 指向含有10个整数的数组的指针。
int (*arr2)[10];
3、一维数组
(1)、一维数组定义方式(如下三种):
// 数据类型 数组名 [ 数组长度 ];
int a[10];
// 用常量来指定数组的大小
int num1;
constexpr int num2;
int a[num1]; //错误,因为 num1 不是常量
int a[num2]; //正确,因为 num2 是常量
// 数据类型 数组名 [ 数组长度 ] = {1,2,3,4};
int b[3] = { 1,2,3 };
// 数据类型 数组名 [] = {1,2,3};
int c[] = { 1,2,3 };
(2)、一维数组名的用途
- 统计数组所有元素在内存中的长度 —— sizeof (数组名)
- 获取数组在内存中的首地址(即数组名)
// 获取数组的长度
int len = sizeof(arr)/sizeof(arr[0]) ;
(3)、C++11 定义了头指针和尾指针的下一个元素的函数:begin,end。如下面的s1数组有4个元素时:
- begin:返回指向数组的首元素位置的指针变量(int *)
- end:返回指向数组尾元素的下一个位置的指针变量(int *)
auto p = begin(s1);
auto e = end(s1);
auto d=p-e; //结果为4
对应的类型如下图所示
4、多维数组
- 严格来讲,C++中并没有多维数组,通常所说的多维数组其实是数组的数组。
(1)、二维数组定义(缺省的元素用0来表示)
int a1[2][3];
int a2[2][3] = { {1,2,3},{4,5,6} };
int a3[2][3] = { 1,2,3,4,5,6 };
int a4[][3] = { 1,2,3,4,5,6 };
(2)、使用范围for来进行遍历多维数组时:除了最内层的循环外,其他的所有循环控制变量都应该是引用类型
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int arr[2][3] = {
{1,2,3},
{4,5,6} };
for (auto &row : arr) // 除最内层外,其他的控制变量都要用引用的类型
{
for (auto col : row)
{
cout << col << " ";
}
cout << endl;
}
cin.get();
}
因为:如果row不是引用类型,编译器在初始化row时,会自动的将这些数组形式的元素转换成指向该数组内首元素的指针。这样row的类型就是 int * ,这样内层循环就不合法了。
二、数组的遍历
1、将数组作为函数的形参,可以用指针或数组名的形式来进行传递实参
// 以指针的形式,arr为数组的首地址,len为数组元素的个数
void PrintArray(int *arr , int len)
// 数组名的形式,看起来更直观。len为数组元素的个数
void PrintArray(int arr[] , int len)
2、关于数组的长度求解。
(1)、如果在传递数组的时候只传递数组名,此时在接受的函数中用 sizeof 将无法求得数组的元素个数。实验示例如下:
#include<iostream>
#include<string>
using namespace std;
// 只传递数组名,在调用函数中求数组长度
void PrintArray01(int *arr)
{
int len01 = sizeof(arr) / sizeof(arr[0]);
cout << "len01 = " << len01 << endl;
for (int i = 0; i < len01; i++)
{
cout << arr[i] << " ";
}
cout << "\n---------------------\n";
}
int main()
{
int a[] = { 5,2,6,8,4,3,7 };
cout << "PrintArray01打印结果为:\n";
PrintArray01(a);
system("pause");
}
运行结果如下:
所以在子函数中用 sizeof(arr) / sizeof(arr[0]) 来求数组的元素时结果为1,因为该函数只接受了数组的第一个元素的地址。
参数的传递是将实参的值赋给形参。然而对于数组来说却是一个例外,因为数组的数据太多了,将其一一赋值既麻烦又浪费空间。所以数组作为参数传递给函数时,只传递了数组首元素的地址,函数在需要用到后面元素时再按照这个地址和数组下标去查找。也就是说后面的元素根本没到函数里来,所以在函数里求不出数组的大小也就不足为奇了。
(2)、为解决以上的问题,需要在定义数组的地方,预先用 sizeof(arr) / sizeof(arr[0]) 来求得数组的元素个数。再将求得的数组元素个数和数组名一起传递给函数。实例如下
#include<iostream>
#include<string>
using namespace std;
// 在定义数组的地方求得数组的元素个数,再作为实参传递过来
void PrintArray02(int* arr, int len)
{
cout << "len = " << len << endl;
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << "\n--------------------\n";
}
int main()
{
int a[] = { 5,2,6,8,4,3,7 };
int len = sizeof(a) / sizeof(a[0]); // 预先求得数组元素的个数
cout << "PrintArray02打印结果为:\n";
PrintArray02(a, len);
system("pause");
}
运行结果如下