在C++编程中,数组是用于存储一组相同类型数据的集合,不同的定义方式会影响数组的生命周期、长度灵活性和操作便利性。掌握多种数组定义方法是写出高质量C++代码的基础。

C++中常见的数组定义方法
1. 静态数组定义
静态数组是长度在编译阶段就确定的数组,存储在栈内存中,生命周期跟随其作用域。定义语法为数据类型 数组名[数组长度],数组长度必须是编译期可确定的常量。
#include <iostream>
using namespace std;
int main() {
// 定义长度为5的int类型静态数组
int static_arr[5];
// 定义时直接初始化
int static_arr2[5] = {1, 2, 3, 4, 5};
// 部分初始化,未初始化的元素默认赋0
int static_arr3[5] = {1, 2};
// 遍历数组输出
for (int i = 0; i < 5; i++) {
cout << static_arr2[i] << " ";
}
return 0;
}
静态数组的优点是访问速度快,不需要手动管理内存,缺点是一旦定义长度无法修改,超出作用域后内存自动释放,不适合需要跨作用域传递大容量数据的场景。
2. 动态数组定义(使用new关键字)
动态数组的长度可以在运行阶段确定,内存分配在堆上,需要手动管理内存释放,避免内存泄漏。定义语法为数据类型* 数组名 = new 数据类型[数组长度],释放时使用delete[] 数组名。
#include <iostream>
using namespace std;
int main() {
int len;
cout << "请输入数组长度:";
cin >> len;
// 运行时确定长度,定义动态数组
int* dynamic_arr = new int[len];
// 给数组元素赋值
for (int i = 0; i < len; i++) {
dynamic_arr[i] = i * 2;
}
// 遍历输出
for (int i = 0; i < len; i++) {
cout << dynamic_arr[i] << " ";
}
// 手动释放堆内存
delete[] dynamic_arr;
dynamic_arr = nullptr;
return 0;
}
动态数组的优势是可以灵活指定长度,适合长度不确定的场景,但缺点是需要手动释放内存,如果忘记调用delete[]会导致内存泄漏,且访问越界时不会直接报错,排查问题难度较大。
3. 使用vector容器定义数组
vector是C++标准库提供的动态数组容器,封装了内存管理逻辑,使用起来更安全便捷,不需要手动释放内存,还提供了丰富的成员函数操作数组。
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 定义空的int类型vector数组
vector<int> vec_arr;
// 定义时指定初始长度和初始值
vector<int> vec_arr2(5, 10); // 5个元素,每个都是10
// 尾部添加元素
vec_arr.push_back(1);
vec_arr.push_back(2);
vec_arr.push_back(3);
// 修改指定位置元素
vec_arr[1] = 20;
// 遍历输出
for (int i = 0; i < vec_arr.size(); i++) {
cout << vec_arr[i] << " ";
}
// vector内存会自动释放,不需要手动操作
return 0;
}
vector几乎覆盖了动态数组的所有使用场景,还支持自动扩容、插入删除元素等操作,是日常开发中最推荐的数组定义方式,除非有特殊性能要求,否则优先选择vector而非手动管理的动态数组。
4. 使用array容器定义数组
array是C++11引入的固定长度数组容器,封装了静态数组的功能,提供了更安全的访问方式和容器通用的接口,内存同样分配在栈上。
#include <iostream>
#include <array>
using namespace std;
int main() {
// 定义长度为5的int类型array数组
array<int, 5> arr_obj;
// 定义时初始化
array<int, 5> arr_obj2 = {1, 2, 3, 4, 5};
// 使用at方法访问,越界会抛出异常
arr_obj2.at(0) = 10;
// 获取数组长度
cout << "数组长度:" << arr_obj2.size() << endl;
return 0;
}
array相比原生静态数组的优势是提供了size()方法获取长度,at()方法访问元素时越界会抛出异常,更安全,适合需要固定长度数组且希望使用容器接口的场景。
不同定义方式的对比
为了更清晰地选择适合的数组定义方式,以下是几种常见方式的特性对比:
| 定义方式 | 长度是否可变 | 内存位置 | 内存管理 | 适用场景 |
|---|---|---|---|---|
| 原生静态数组 | 否 | 栈 | 自动管理 | 长度固定、小容量、作用域内使用的场景 |
| new动态数组 | 是 | 堆 | 手动释放 | 需要动态长度、且明确需要手动控制内存的场景 |
| vector容器 | 是 | 堆(内部管理) | 自动管理 | 绝大多数动态长度数组场景 |
| array容器 | 否 | 栈 | 自动管理 | 固定长度、需要容器接口的场景 |
定义数组的注意事项
- 原生数组和动态数组访问元素时不会做越界检查,使用下标访问前要确保索引在合法范围内,避免访问非法内存。
- 动态数组使用new[]分配内存后,必须使用delete[]释放,不能用delete,否则会导致部分内存未释放的问题。
- 如果数组长度较小且固定,优先选择array或原生静态数组,性能比vector更好;如果长度不确定,优先选择vector,减少内存管理风险。
- 数组作为函数参数传递时,原生数组会退化为指针,无法直接获取数组长度,建议传递时同时传入长度参数,或者使用vector、array容器传递,避免长度丢失的问题。