C + + 基础(02)—— 数组

一、基本数组

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];

// 利用 new 来创建一个有10个元素的数组,返回的是指向该数组首地址的指针
int *b=new int[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 };

//内置数组不支持拷贝或赋值
int e[5]={1,2,3,4,5};
int f[5]=e;    //错误,内置的数组不能进行拷贝,因为e只是表示数组的首元素地址

【注】数组的维度必须是一个常量表达式,在C++初始化数组时,数组的长度必须是一个常量,不能是变量(常变量除外)

int num1=10;
int arr1[num1]; // 错误,因为num为变量

const int num2=10;
int arr2[num2]; //正确

 (2)、将一位数组初始化为0的几种方式:

int arr1[10]; // arr1默认是随机值,在此为 -858993460

int arr2[10] = { 0 };// arr2被初始化为0

int arr3[10];
memset(arr3, 0, sizeof(int) * 10); // arr3被初始化为0

(3)、一维数组名的用途

  • 统计数组所有元素在内存中的长度 —— sizeof (数组名)
  • 获取数组在内存中的首地址(即数组名)
// 获取数组的长度
int len = sizeof(arr)/sizeof(arr[0]) ;

 (4)、C++11 定义了头指针和尾指针的下一个元素的函数:begin,end。如下面的s1数组有4个元素时:

  • begin:返回指向数组的首元素位置的指针变量(int *
  • end:返回指向数组尾元素的下一个位置的指针变量(int *

               

int s1[4] = {1,2,3,4};
auto p = begin(s1);//等效于: int *pbeg=&s1[0];
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");
}

运行结果如下

 

 


【注意】:C++11 引入数组容器 array 。 该容器可以支持拷贝初始化的操作

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值