数组
2026-07-18 20:06:31
发布于:上海
一、数组基础概念
1. 定义
数组是相同数据类型元素的有序集合,一段连续的内存空间,通过下标(索引)访问元素。
下标从 0 开始,最大下标 = 数组长度 - 1
数组名本质是首元素地址(常量指针,不能修改指向)
2. 分类
一维数组
二维 / 多维数组
字符数组(字符串)
动态数组(堆内存 new[] / delete[])
二、一维数组
1. 声明语法
数据类型 数组名[数组长度];
限制:[] 内长度常量 / 常量表达式,C++ 标准下不能直接用普通变量(变长数组 VLA 仅 GCC 扩展,不跨平台)。
四种初始化方式
// 方式1:先声明,后逐个赋值
int arr[5];
arr[0] = 10;
arr[1] = 20;
// 方式2:大括号整体初始化
int arr1[5] = {1,2,3}; // 未赋值元素自动补0
// 方式3:省略长度,自动推导长度
int arr2[] = {10,20,30}; // 长度=3
// 方式4:全部置0
int arr3[10] = {0};
- 访问与遍历
#include <iostream>
using namespace std;
int main()
{
int arr[4] = {1,3,5,7};
// for循环遍历
for(int i = 0; i < 4; i++)
{
cout << arr[i] << " ";
}
// C++11 范围for(只读/修改)
for(int x : arr) cout << x; // 只读
for(int &x : arr) x *= 2; // 引用修改元素
return 0;
}
3. 数组长度获取
静态数组(栈上)
int arr[10];
// sizeof(数组名) = 总字节数
// sizeof(元素) = 单个元素字节
int len = sizeof(arr) / sizeof(arr[0]);
注意:数组作为函数参数传递时,数组名退化为指针,sizeof 无法获取真实长度
三、二维数组
1. 本质
数组的数组,内存依旧连续;逻辑上分行、列。
语法:类型 数组名[行数][列数]
// 完整赋值
int mat[2][3] = {
{1,2,3},
{4,5,6}
};
// 简写,自动分行
int mat2[2][3] = {1,2,3,4,5,6};
// 部分赋值,剩余补0
int mat3[2][3] = {{1},{2}};
// 行数可省略,列数不能省(自动推导行数)
int mat4[][3] = {1,2,3,4,5,6}; // 2行3列
3. 遍历
int mat[2][3] = {{1,2},{3,4}};
int rows = sizeof(mat)/sizeof(mat[0]);
int cols = sizeof(mat[0])/sizeof(mat[0][0]);
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
四、字符数组与 C 风格字符串
1. 普通字符数组
char ch[5] = {'a','b','c'}; // 末尾自动补'\0'
2. 字符串(必须以 \0 结束标记
// 方式1:双引号自动追加'\0'
char str[10] = "hello";
// 等价写法
char str2[10] = {'h','e','l','l','o','\0'};
| 函数 | 作用 |
|---|---|
| strlen(str) | 获取有效字符长度(不含<>) |
| strcpy(a,b) | 把 b 复制到 a,不安全(无长度检查) |
| strncpy(a,b,n) | 最多复制 n 个字符,安全版 |
| strcmp(a,b) | 比较字符串,相等返回 0 |
| strcat(a,b) | 字符串拼接 |
| 4. C++ string 对比字符数组 | |
| string 是标准库字符串类(<string>),封装动态内存,无需手动处理<>,推荐优先使用。 |
#include <string>
string s = "c++";
s += " array";
cout << s.size();
五、数组作为函数参数
1. 一维数组传参
数组名传递时退化为指针,丢失长度信息,必须额外传长度:
// 三种等价写法
void printArr(int arr[], int len);
void printArr(int arr[100], int len);
void printArr(int *arr, int len);
// 调用
int a[5] = {1,2,3,4,5};
printArr(a, 5);
六、动态数组(堆内存 new /delete)
静态数组在栈上,大小固定;动态数组在堆,运行时指定长度。
1. 一维动态数组
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
// 分配堆内存
int *p = new int[n];
// 赋值
for(int i=0; i<n; i++) p[i] = i;
// 释放内存,必须加[]
delete[] p;
p = nullptr; // 置空防止野指针
return 0;
}
2. 二维动态数组(指针数组)
int rows, cols;
cin >> rows >> cols;
int **mat = new int*[rows];
for(int i=0; i<rows; i++)
{
mat[i] = new int[cols];
}
// 使用 mat[i][j]
// 释放:先释放每行,再释放行指针
for(int i=0; i<rows; i++) delete[] mat[i];
delete[] mat;
mat = nullptr;
注意事项
1.new[] 必须配对 delete[],漏释放造成内存泄漏
2.释放后指针置空,避免野指针
3.堆内存生命周期不受函数限制,手动管理
七、数组常见易错点
1.下标越界
访问 arr[len]、arr[-1],编译器不报错,但读写非法内存,程序崩溃 / 乱码。
2.变长数组 VLA
int n=5; int arr[n]; 非标准 C++,仅 GCC 支持,VS 编译报错,不要使用,改用new[]。
3.函数内 sizeof 获取数组长度
数组退化为指针,sizeof(arr) 得到指针大小(8 字节 64 位),不是数组总长度。
4.字符串忘记 '\0'
字符数组存字符串必须预留一个位置给结束符。
5.动态数组释放错误
只用delete不用delete[],或重复释放同一块内存。
6.数组名不能自增自减
arr++ 非法;指针p++可以。
八、数组与 vector(补充:现代 C++ 推荐)
原生数组内存管理麻烦,C++ 推荐容器 std::vector(动态数组,封装堆内存,自动释放)
#include <vector>
vector<int> v = {1,2,3};
v.push_back(4); // 尾部添加
cout << v.size(); // 获取长度
// 支持下标访问 v[0],越界可at()抛异常 v.at(0)
九、核心总结速记
静态数组:栈内存,长度编译期常量,sizeof(arr)可求长度;传参变指针。
二维数组:列固定,行可变,连续内存。
C 字符串:char[],以\0结尾,<cstring>操作函数。
动态数组:new[]/delete[] 堆内存,手动释放。
现代替代:std::vector,自动管理内存,安全易用。
禁忌:下标越界、VLA、忘记释放堆内存、数组名赋值修改。
这里空空如也

有帮助,赞一个