普通的内置数组语法基础
数组即一组类型相同的元素组成的集合,存放在计算机内存的一片连续存储空间里,空间大小=元素个数x元素类型所占字节大小。C++提供一种内置的数组,后面将会用C++ 11新增更方便、安全的模板类array替代它,下面先介绍一下数组的语法。
首先说明一个概念:什么是普通指针?什么是数组指针?什么是指针数组?
普通指针:顾名思义就是基本数据类型的指针 如 int *类型,string *等,有自己的内存空间,其上存储的是所指向变量的地址值,对其解引用得到变量的引用,可直接对变量进行读写(如没有const限制);在数组中,普通指针就是指向一维数组元素的指针。
数组指针:又叫行指针,定义如 int ( *)[]这样,指向一整个数组的指针,存储的是整个数组的地址(虽然打印出来和首元素地址一样,但不是一个概念),对其解引用得到的是一个数组,而不是一个数组的元素,主要用在二维数组中,用于指向二维数组中的每个一维数组。
在一维数组里,数组名arr表示首元素的地址,&arr表示整个数组的地址,前者是int *类型,后者是 int(*)[]类型;
同样,在二维数组里 arr表示第一个数组的地址,&arr是整个二维数组地址,前者是int (*)[]类型,后者是 int(*)[][]类型;

一,一维数组
①数组的定义:
T a[n]; T:元素的数据类型 a:数组名 n:数组的长度即元素个数,注意,定义数组时,长度必须是明确的,只能是常量或常量表达式。
例:
int a[10]; //定义数组a时,系统会分配一片连续的内存空间,空间大小为10*4=40字节,用于存储10个int型变量,默认变量值都为0,空间的名字为a.
②数组初始化方法
最常用的列表初始化:
int a[5]={1,2,3} ; //缺项默认初始化为0
int a[5]{1,2,3};
int a[]{1,2,4}
注意,C++中数组不支持用一个数组来初始化另一个数组,或者用一个数组赋值给另一个数组,只能每个元素逐个copy,这就是数组不方便的地方之一。
③复杂数组的声明:
(1)指针数组定义:
int * ptrl[10]; //定义有10个整型指针的数组
(2)数组元素类型不能是引用,必须是实际存在的东西:
int & ptrl[10]; //错误
(3) int (*ptrl)[10]=&arr //定义一个数组指针ptrl,指向一个有10个int型元素的数组,对指针解引用得到一个数组,元素引用使用(*ptrl)[i]。

概念引入: 数组指针:指向数组的指针,解引用得到整个数组, 指针数组:表示存放的元素类型为指针的数组
(4) int (& ptrl)[10]=arr; //声明一个引用ptrl, ptrl是一个有十个int型变量的数组的引用(别名),数组名为arr,

③数组与指针
概念1:通过数组名和元素下标对元素的访问,本质上是一种指针访问,数组名就是首元素的地址值。
int arr[10];
arr[i]---------等同于--------*(arr +i) //arr为首元素地址 ,arr==&arr[0]
例:
注意:&arr打印出来也是首元素的地址值,但它和首元素地址值不是一个概念,它也不是普通的指针类型
如:
int arr[10]; //&arr是 int(*)[10]的类型,即数组指针或者叫行指针,而不是int *类型,主要用于二维数组。
进而得到概念2::可以使用一个指针来指向数组的某个元素,然后用这个指针通过类似数组名和下标的方式来引用数组的元素。
例:

另外,auto p3(arr); //因为数组不允许用一个数组初始化另一个数组,所以这里的arr指的是&arr[0],p3是一个指针类型。
概念3:
指向数组元素的指针就是数组的迭代器,支持迭代器的操作:
int *p1=&arr[i];
int *p2=&arr[j];
p1++ :指向数组的下一个元素,可以指向尾后,但不能对尾后进行解引用,因为元素不存在
p1-- : 指向上一个元素
p1+k:指向向后移动k个元素位置后的元素。
p2-p1:所指向的元素下标相减
p2<p1:比较所指向的元素下标大小。
④begin(arr)和end(arr)方法
数组的指针就是它的迭代器,类似vector和array,数组同样提供了获取指向首元素和尾后元素指针的方法begin(arr)和end(arr):

⑤数组的不安全性
C++和C都不会检查数组下标是否合法,像下面这种情况:
int arr[3]{1,2,3};
arr[-1]=3;
这里将一个数组3存入数组存储空间以外一个元素位置后的空间,然后程序并不会报错,所以如果有类似写法将可能埋下隐患,不好排查。
二,多维数组
下面来学习多维数组的相关知识。
概念:一个二维数组可以看做是由一组一维数组构成的一维数组,数组的每个元素为一个一维数组;同理,可以将三维数组看做是由一组二维数组组成的一维数组,数组元素为二维数组。
按这样的思路,那么二维数组的数组名或者首元素地址即为第一个数组的地址(或者说第一行数组的地址),且对地址进行解引用得到的地址上的值为一整个一维数组;同理三维数组名或三维数组首元素地址即为第一个二维数组的地址;且地址的解引用得到的是地址上的二维数组。
理解了上面的概念,下面来举例多维数组的操作(以二维举例):
①二维数组初始化:
int arr[2][3]={{1,2},{3,4}};
int arr[2][3]={{1},{2}};
int arr[2][3]={1,2,3,4,5,6}
②二维数组的一维引用
对二维数组的每个数组进行引用:
int arr[2][3];
int (&ptrl)[3]=arr[0]; //这里声明ptrl是一个对长度为3的int型数组的引用,引用的对象是arr[0],即二维数组arr的第一个数组(第一行)
ptrl[0],ptrl[1],ptrl[2]; //同arr[0][0],arr[0][1],arr[0][2]都是对arr第一个数组的元素的引用。
③二维数组的数组指针
可以使用数组指针或叫行指针来指向二维数组的每个一维数组,解引用得到每个一维数组
int arr[2][3];
int(*p)[3]=&arr[0];
cout<<(*p)[0]; //打印得到arr[0][0];
④使用引用遍历二维数组:

⑤指针遍历二维数组

浙公网安备 33010602011771号