在第 8 节中,我们学习了指针的基本概念——如何声明指针、取地址、解引用。指针的强大之处不仅在于它能指向已有的变量,更在于它能让我们在程序运行时动态申请内存。本节将介绍new和delete这对运算符,带你掌握 C++ 中动态内存管理的核心技能。
1. 栈内存与堆内存
在 C++ 程序中,内存主要分为几个区域,其中最常接触的是栈(Stack)和堆(Heap)。
1.1 栈内存
栈内存由编译器自动管理。当你声明一个局部变量时,它就被分配在栈上;当变量离开作用域时,栈内存自动释放。
voidfoo(){intx=10;// x 分配在栈上intarr[5]={};// arr 也分配在栈上}// 离开函数,x 和 arr 自动释放栈内存的特点是:分配和释放速度极快,但空间有限(通常只有几 MB),且大小必须在编译时确定。
1.2 堆内存
堆内存由程序员手动管理,空间更大,适合存放那些大小不确定或需要长期存活的数据。
voidfoo(){int*p=newint(42);// 在堆上分配一个 int// ... 使用 *p ...deletep;// 手动释放}堆内存的特点是:空间较大,分配速度相对较慢,且必须由程序员手动释放,否则会造成内存泄漏。
| 对比项 | 栈内存 | 堆内存 |
|---|---|---|
| 管理方式 | 编译器自动 | 程序员手动 |
| 分配速度 | 快 | 较慢 |
| 空间大小 | 较小(通常几 MB) | 较大(取决于系统) |
| 大小确定时机 | 编译时 | 运行时 |
| 是否需要手动释放 | 否 | 是 |
2. new 运算符
new运算符用于在堆上分配内存,并返回指向该内存的指针。
2.1 分配单个变量
int*p=newint(42);// 在堆上分配一个 int,初始值为 42double*q=newdouble;// 在堆上分配一个 double,未初始化new int(42)会做两件事:在堆上申请一块足够存放int的内存,然后将这块内存的值初始化为42,最后返回其地址。如果不提供初始值(如new double),内存中的值是未定义的。
2.2 分配数组
int*arr=newint[10];// 在堆上分配 10 个 int 的数组double*darr=newdouble[n];// n 可以是运行时才确定的变量new int[10]会在堆上连续分配 10 个int大小的空间,并返回首元素的指针。注意方括号[]不能省略。数组长度可以是变量——这是