C++动态内存分配:new与delete的基础用法

在C++中,我们经常需要处理数据的存储问题。有时候,我们可能不知道需要多少内存,或者需要根据程序运行时的情况来动态调整内存大小。这时候,静态内存分配(比如直接定义变量)就不够用了,这就需要用到动态内存分配。

为什么需要动态内存分配?

我们平时写代码时,静态内存分配(比如 int a;char s[20];)是在编译时就确定了内存大小,由编译器自动管理。但如果遇到这样的场景:需要存储一组不确定数量的数据(比如用户输入的多个数字),或者临时需要一块很大的内存,静态内存就显得不够灵活了。

动态内存分配允许我们在运行时根据实际需求向“堆”申请内存,使用完后再手动释放。堆是一块独立的内存区域,大小相对灵活,但需要我们自己负责管理,避免内存泄漏。

动态内存与堆/栈的简单区别

  • 栈(Stack):由编译器自动分配和释放,用于存储局部变量、函数参数等,内存大小有限且速度快。
  • 堆(Heap):程序运行时动态申请的内存区域,大小灵活但由程序员手动管理,需要显式释放。

newdelete 就是用来操作堆内存的核心工具。

new 操作符:在堆上分配内存

要在堆上申请内存,我们使用 new 操作符。它的语法很简单:

1. 分配单个对象

类型* 指针变量 = new 类型;  // 分配一个该类型的内存空间

例如,分配一个 int 类型的动态变量:

int* p = new int;  // p 指向堆上一个 int 类型的内存空间

此时,p 是一个指针,我们可以通过 *p 访问或修改这块内存的值:

*p = 100;  // 将 100 存入 p 指向的内存
cout << "动态变量的值:" << *p << endl;  // 输出 100

如果需要在分配时初始化内存,可以直接在 new 后加括号传入初始值:

int* num = new int(20);  // 直接初始化为 20
cout << "初始化后的变量:" << *num << endl;  // 输出 20

2. 分配数组

如果需要一组数据(比如数组),可以用 new[] 来分配:

类型* 数组指针 = new 类型[数组大小];  // 分配数组内存

例如,分配一个包含 5 个 int 的动态数组:

int* arr = new int[5];  // arr 指向一个有 5 个 int 的数组

数组元素默认不初始化(值可能是随机的),如果需要初始化(比如全为 0),可以写成:

int* arr = new int[5]();  // 每个元素被初始化为 0

使用数组时,可以通过下标访问元素:

for (int i = 0; i < 5; ++i) {
    arr[i] = i * 2;  // 数组赋值:0, 2, 4, 6, 8
}
// 打印数组元素
for (int i = 0; i < 5; ++i) {
    cout << "arr[" << i << "] = " << arr[i] << endl;
}

delete 操作符:释放堆内存

new 分配的内存不会自动释放,必须用 deletedelete[] 手动释放,否则会导致内存泄漏(程序占用的内存越来越多,最终崩溃)。

1. 释放单个对象

如果用 new 分配了单个对象,用 delete 释放:

int* p = new int(100);
// 使用完后释放内存
delete p;  // p 指向的堆内存被释放,之后不能再用 *p

2. 释放数组

如果用 new[] 分配了数组,必须用 delete[] 释放,否则只会释放数组第一个元素的内存,导致内存泄漏:

int* arr = new int[5];
// 使用完后释放数组
delete[] arr;  // 必须用 delete[],不能用 delete!

常见错误与注意事项

  1. 忘记释放内存:用 new 分配后不 delete,会导致内存泄漏。例如:
   int* p = new int(5);
   // 使用 p...
   // 忘记写 delete p; 这里内存会一直占用
  1. 数组用 delete 而非 delete[]:例如:
   int* arr = new int[10];
   delete arr;  // 错误!应该用 delete[] arr;

这样只会释放数组第一个元素的内存,剩下的 9 个元素内存永远不会被释放。

  1. 重复释放内存:同一个指针不能 delete 两次,否则会导致程序崩溃:
   int* p = new int;
   delete p;
   delete p;  // 错误!重复释放,未定义行为

总结

动态内存分配让我们可以在运行时灵活管理内存,核心工具是 newdelete
- new 用于在堆上分配单个对象或数组内存,语法分别为 new 类型new 类型[大小]
- delete 用于释放单个对象的内存,delete[] 用于释放数组的内存;
- 务必用对应方式释放内存(单个对象用 delete,数组用 delete[]),避免内存泄漏或程序崩溃。

合理使用动态内存,可以让程序更高效地利用内存资源,但要时刻注意内存的分配与释放,养成良好的编程习惯。

Xiaoye