在C++中,使用new
操作符动态分配数组空间是一种常见的内存管理方式。以下是关于new
分配数组的详细说明和示例:
1. 一维数组的动态分配
语法
cpp
type* array = new type[size]; // 分配size个type类型的元素
示例
cpp
int n = 5;
int* arr = new int[n]; // 分配包含5个整数的数组
// 初始化数组元素
for (int i = 0; i < n; i++) {
arr[i] = i * 2;
}
// 使用后释放内存
delete[] arr; // 必须使用delete[]释放数组内存
注意事项
-
内存释放 :必须使用
delete[]
释放数组内存,否则会导致内存泄漏。 -
未初始化元素 :对于基本类型(如
int
、double
),元素值是未定义的;对于类类型,会调用默认构造函数。 -
值初始化 :可使用
new type[size]()
强制初始化为0或默认值:cppint* arr = new int[5](); // 所有元素初始化为0
2. 二维数组的动态分配
2.1 方法一:使用指针数组(非连续内存)
cpp
int rows = 3;
int cols = 4;
// 分配指针数组(每一行是一个指针)
int** arr = new int*[rows];
// 为每一行分配内存
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
}
// 使用数组
arr[0][0] = 10;
// 释放内存(必须按相反顺序)
for (int i = 0; i < rows; i++) {
delete[] arr[i]; // 释放每一行
}
delete[] arr; // 释放指针数组
2.2 方法二:使用连续内存块(更高效)
cpp
int rows = 3;
int cols = 4;
// 分配连续内存块
int* arr = new int[rows * cols];
// 访问元素(手动计算索引)
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i * cols + j] = i + j; // 等价于arr[i][j]
}
}
// 释放内存
delete[] arr;
3. 多维数组的动态分配
三维数组示例
cpp
int x = 2, y = 3, z = 4;
// 分配三维数组
int*** arr = new int**[x];
for (int i = 0; i < x; i++) {
arr[i] = new int*[y];
for (int j = 0; j < y; j++) {
arr[i][j] = new int[z];
}
}
// 释放内存
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
delete[] arr[i][j];
}
delete[] arr[i];
}
delete[] arr;
4. 动态数组的初始化
4.1 基本类型初始化为0
cpp
int* arr = new int[5](); // 所有元素初始化为0
4.2 使用循环初始化
cpp
int* arr = new int[5];
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
}
4.3 类类型自动调用构造函数
cpp
class MyClass {
public:
MyClass() { std::cout << "Constructed\n"; }
};
MyClass* arr = new MyClass[3]; // 自动调用3次默认构造函数
delete[] arr; // 自动调用3次析构函数
5. 使用智能指针管理动态数组(C++11+)
为避免手动内存管理,推荐使用std::unique_ptr
或std::shared_ptr
:
一维数组
cpp
#include <memory>
// 使用unique_ptr管理数组
std::unique_ptr<int[]> arr(new int[5]()); // 初始化为0
// 访问元素
arr[0] = 100;
// 无需手动delete,离开作用域时自动释放
二维数组(使用vector更简单)
cpp
#include <vector>
int rows = 3, cols = 4;
std::vector<std::vector<int>> arr(rows, std::vector<int>(cols, 0));
// 访问元素
arr[1][2] = 50;
// 自动管理内存
6. 常见错误与注意事项
- 内存泄漏 :忘记使用
delete[]
释放内存。 - 越界访问 :动态数组不会检查索引范围,需自行确保
index < size
。 - 浅拷贝问题:若将动态数组指针赋值给另一个指针,两者指向同一块内存,可能导致双重释放。
- 性能开销 :多层
new
(如二维数组的指针数组)会增加内存碎片,连续内存布局(如方法2.2)更高效。
总结
场景 | 推荐方法 |
---|---|
一维动态数组 | new type[size] + delete[] |
二维动态数组(简单) | std::vector<std::vector<int>> |
二维动态数组(高性能) | 连续内存块 + 手动索引计算 |
避免内存泄漏 | std::unique_ptr<int[]> |
动态内存分配提供了灵活性,但需谨慎管理内存以避免错误。优先使用标准库容器(如vector
)和智能指针,减少手动new/delete
的使用。