数组

一、数组的概念

数组是一种数据格式,可以存储多个同类型的值

数组是一种复合类型

数组的实质是申请一片连续的内存,存储同类型的变量

二、数组的声明

一般形式:

1
2
typeName arrayName[arraySize];
数据类型 数组标识符["数组长度"];

三、数组的“静态性”

数组是一种静态的数据类型,体现在

  • 数组长度必须是$\textcolor{red}{常量,字面值,表达式}$

(也就是编译过程中已知的数字,不能作动态定义)

  • 数组长度必须是正整数

四、用索引访问数组元素

数组索引从0到arraysize-1

1
2
3
example:
int array[10] = {0};
cout << array[0];

这并不意味着,数组的第一个元素叫做第0个元素

事实上,数组索引是指针相对于数组第一个元素地址的偏移量

那么自然第一个元素的偏移量是0

索引是可以是变量,但必须是整数

由于数组名指向数组的第一个元素地址,而索引其实就是跳转到

1
2
&array[i] = array + i * sizeof(int) / sizeof(int)
\\注意此处i本身是intsizeof的返回值也是int,输出是int的平方,应该除以int

注意

1
array本身就是地址,如果&array将变成地址的地址,类似二维数组

五、数组的初始化

1
typeName arrayName[arraySize] = {value1,value2,...};
1
int array[4] = {1,2,3,4};

不过,数组的初始化可以不完全,例如

1
int array[4] = {1,2};

编译器会自动将后面的元素补成0,当元素个数较多时,可以实现快速初始化

值得注意的是

只有在定义的时候才能初始化数组

1
2
int array[4];
array[4] = {1.2.3.4}

这是不被允许的

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
using namespace std;
int main()
{
int array[4];
array[4] = {1,2,3,4 };
for (int i = 0; i < 4; i++)
{
cout << array[i];
}
}

编译器反馈如下

QQ_1731931863751

这种操作实际上是给array[4]这个数组成员赋值,因此是不被允许

所以我们说,数组只能在声明的时候初始化

不过,可以使用指针实现,不在声明的时候初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;
int main()
{
int array[4];
int* p =array;
*(p) = 1;
p += 1;
*(p) = 2;
p += 1;
*(p) = 3;
p += 1;
*(p) = 4;
for (int i = 0; i < 4; i++)
{
cout << array[i];
}
}

六、for循环输出数组元素

1
2
3
4
for(int i = 0;i<arraysize;i++)
{
cout << array[i];
}

七、以数组为参数的函数

1
int Max(int[],int size)

C++是强类型的,数组的元素个数不同,数组的类型就不同,因此没必要传入数组的大小,即使传入,编译器也会忽视

八、动态数组

我们知道指针是可以指定一片空间的,使用new就可以创建一片内存,并且指针可以进行加法,从而实现位置的偏移,因此,指针可以充当数组的

创建方式如下

1
2
3
4
5
int* p = new int[size];
for(int i = 0;i<size;i++)
{
cin >> p[i];
}

随后你可以使用p[i]来访问创建动态数组中的元素了;

创建二维数组同理,但你需要一个指向指针的指针,即指向int类型的指针,我们用int*来表示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int m;
cin >> m;
int** light = new int* [m];
for (int i = 0; i < m; i++)
{
light[i] = new int[n];
}
for (int i = 0; i < m; i++)
{
cin >> light[i][0] >> light[i][1];
}
for (int i = 0; i < m; i++)
{
cout << light[i][0] << " " << light[i][1] << endl;
}

这是一种生成$m\times 2$矩阵的方式,不过,初始化这种二维数组,比较复杂,可以使用vector来规避

还有另一种创建二维数组的方式

1
2
3
4
5
int m;
cin >> m;
int (*rows)[m]; \\定义一个int指针的数组
rows = new int[m]; \\指针指向int空间
\\这将会生成一个m*m的矩阵,由于我们定义了一个指针数组,那么,这样就可规避循环初始化

九、vector STL

  • vector的声明与初始化

1
#include<vector>

使用vector前,你需要引入vector库

vector顾名思义,就是一个向量,也是一种动态数组,功能与python中的list几乎完全一致

我们使用

1
2
vector<int> v;
//如果仅仅声明v,其容量为0,编译器认为是empty

来声明一个vector对象

如果想要初始化,可以使用

1
vector<int> v(allocator,value)

即在括号中填入容量,初始值

当然也可以直接像数组一样初始化,访问方式也和数组一样

1
2
vector<int> v = {1,2,3,4,5};
v[0] = 1;

还可以将其他vector赋值来初始化

1
2
vector<int> v(v0)
// v0也是一个vector对象

当然vector也可以声明动态二维数组

1
vector<vector<int>> v(allocator,vector<int>(allocator,value))

声明方式就是一维vector的套娃

  • vector的强大功能

vector的强大功能在于可以像list一样管理一个栈(队列)

1
2
3
v.push_back(value);
//入栈,将一个值推入vector的末尾
相当于python中的list.append(value)
1
2
v.pop_back();
//出栈,删掉末尾的元素;类似python的list.pop()