ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

小学生学C++编程语法知识(C++申请内存与释放内存)

2026/8/15 15:56:34 拓冰建站 浏览量
小学生学C++编程语法知识(C++申请内存与释放内存)


newdeletenew[]delete[]allocator都在解决一个问题:

“我向计算机借了一块内存,用完以后应该怎样把它还回去?”


一、先认识一个最重要的规则

同学们先记住这一张表:

申请内存释放内存
new intdelete p
new int[10]delete[] p
allocator.allocate(10)allocator.deallocate(p, 10)

也就是:

new → delete new[] → delete[] allocate → deallocate

谁借的,就尽量用对应的方法还。

这是今天最重要的规律。


二、先理解new

假设我们写:

int *p = new int;

可以把它理解成:

“计算机,请给我一间房子,里面住一个int。”

计算机就找了一块内存:

堆区 ┌─────────────┐ │ int │ │ 10 │ └─────────────┘ ↑ p

例如:

*p = 10; cout << *p;

输出:

10

但是这块内存是我们自己申请的。

所以用完以后:

delete p;

就是告诉计算机:

“这间房子我不用了,可以收回去了。”


三、delete p到底做了什么?

看这个例子:

int *p = new int; *p = 100; delete p;

可以理解成:

new int ↓ 申请一块内存 ↓ ┌─────────┐ │ 100 │ └─────────┘ ↑ p delete p ↓ 把这块内存还给系统

注意:

delete p删除的不是变量p本身。

这一点非常重要!

int *p = new int;

这里其实有两个东西:

p │ │ 保存一个地址 ↓ ┌──────────┐ │ int对象 │ └──────────┘

执行:

delete p;

删除的是:

┌──────────┐ │ int对象 │ └──────────┘

而不是指针变量:

p

所以p这个指针变量本身还存在,只不过它里面原来的地址已经不能再拿来访问那个对象了。


四、那么为什么有delete[] p

因为我们还可以一次申请很多个对象。

比如:

int *p = new int[5];

意思是:

“请给我连续的5个int房间。”

内存可以想象成:

p ↓ ┌────┬────┬────┬────┬────┐ │ 10 │ 20 │ 30 │ 40 │ 50 │ └────┴────┴────┴────┴────┘ 0 1 2 3 4

于是:

p[0] = 10; p[1] = 20; p[2] = 30; p[3] = 40; p[4] = 50;

因为我们申请的是:

new int[5]

所以最后必须:

delete[] p;

而不是:

delete p;

五、deletedelete[]的区别

这可以记成一句特别简单的话:

一个对象用delete,一群对象用delete[]

例如:

一个int

int *p = new int; delete p;

对应:

new ↓ 一个对象 ↓ delete

一组int

int *p = new int[10]; delete[] p;

对应:

new[] ↓ 多个对象 ↓ delete[]

六、为什么不能搞错?

例如:

int *p = new int[10]; delete p; // ❌

这是错误的。

因为:

new int[10]

delete p

不是一对。

正确的是:

int *p = new int[10]; delete[] p; // ✅

反过来也一样:

int *p = new int; delete[] p; // ❌

应该:

delete p; // ✅

七、这里还有一个非常重要的原因:析构函数

如果是简单的:

int double char

同学们可能觉得:

“反正都是内存,还不都是还回去吗?”

但是 C++ 里面还有一个非常重要的东西:

对象的析构函数。

例如:

class Student { public: ~Student() { cout << "学生对象消失了"; } };

如果:

Student *p = new Student[3]; delete[] p;

那么 C++ 会正确处理这三个对象的销毁。

可以理解成:

Student 1 → 析构 Student 2 → 析构 Student 3 → 析构 ↓ 释放整块内存

所以:

delete[]不只是“释放一大片内存”,还要正确处理这一组对象的生命周期。

这也是为什么new[]必须对应delete[]


八、现在来看一个新朋友:allocator

前面我们学习:

new

它其实做了两件事情:

① 申请内存

② 创建对象

而 C++ 的:

allocator

可以让我们把这两件事情拆开。

这就是它最重要的意义。


九、把new想成“一条龙服务”

例如:

Student *p = new Student;

可以理解为你去了一家酒店:

“我要一个已经准备好的房间。”

酒店直接帮你:

找房子 ↓ 分配内存 ↓ 创建 Student ↓ 交给你

所以:

new Student

相当于:

申请内存 + 构造对象


十、allocator可以把事情拆开

例如:

allocator<int> alloc;

可以理解成:

“我有一个专门负责管理int内存的管理员。”

然后:

int *p = alloc.allocate(5);

它的意思是:

给我一块能够放下 5 个int的原始内存。

注意!

这里有一个非常重要的地方:

alloc.allocate(5);

只是申请内存。

它并没有自动把 5 个int都创建出来。


十一、allocatenew[]最大的区别

看:

int *p = new int[5];

这里:

new[] ↓ 申请内存 + 创建5个 int 对象

而:

allocator<int> alloc; int *p = alloc.allocate(5);

只有:

allocate ↓ 申请能够容纳5个 int 的内存

还没有真正构造对象。

可以把它想象成:

allocate(5) ┌────┬────┬────┬────┬────┐ │ 空 │ 空 │ 空 │ 空 │ 空 │ └────┴────┴────┴────┴────┘ 只是准备了5个“座位”

十二、那对象怎么创建?

这就需要进一步使用构造操作。

现代 C++ 可以使用:

std::allocator<int> alloc; int *p = alloc.allocate(5); alloc.construct(p, 10); alloc.construct(p + 1, 20); alloc.construct(p + 2, 30);

现在才真正创建了对象。

可以理解成:

allocate ↓ 准备5个座位 ↓ construct ↓ 让对象坐进去

例如:

allocate(5) ┌────┬────┬────┬────┬────┐ │ 空 │ 空 │ 空 │ 空 │ 空 │ └────┴────┴────┴────┴────┘ construct(p, 10) ┌────┬────┬────┬────┬────┐ │ 10 │ 空 │ 空 │ 空 │ 空 │ └────┴────┴────┴────┴────┘

十三、用完怎么办?

如果使用了:

allocate()

就应该使用:

deallocate()

例如:

allocator<int> alloc; int *p = alloc.allocate(5); // 使用内存…… alloc.deallocate(p, 5);

所以:

allocate ↓ deallocate

是一对。


十四、把三组关系放在一起

这是今天最值得记住的一张表:

申请作用释放
new T申请内存 + 创建一个对象delete p
new T[n]申请内存 + 创建 n 个对象delete[] p
allocator.allocate(n)只申请原始内存allocator.deallocate(p,n)

可以记成:

申请 释放 new T ───────────────→ delete p new T[n] ──────────────→ delete[] p allocator.allocate(n) ───────→ allocator.deallocate(p,n)

十五、一个特别形象的比喻

假设学校有一个仓库。

new

你对管理员说:

“给我一个已经装修好的房间。”

管理员:

找房间 ↓ 装修 ↓ 交给你

这就是:

new Student

new[]

你说:

“给我10个已经装修好的房间。”

管理员:

找10个房间 ↓ 全部装修 ↓ 交给你

对应:

new Student[10]

最后:

delete[] p;

管理员把这10个房间都处理掉。


allocator

这时候你说:

“先给我一块空地,我自己决定什么时候盖房子。”

管理员:

alloc.allocate(10);

只给你:

一块可以放10个对象的空间

然后你自己:

alloc.construct(...)

决定什么时候建对象。

最后:

alloc.destroy(...)

销毁对象,再:

alloc.deallocate(...)

归还内存。

所以:

allocator 给了程序员更精细的“内存控制权”。


十六、为什么 C++ 要搞这么复杂?

同学们可能会问:

“直接new不就行了吗?为什么还要allocator?”

这是一个非常好的问题。

因为很多时候,我们并不希望:

申请内存 ↓ 马上创建对象

而是希望:

先准备一大片内存 ↓ 真正需要的时候再创建对象 ↓ 不用的时候销毁对象 ↓ 最后再释放内存

这对于 C++ 的一些底层数据结构非常重要。

例如:

vector

内部就需要非常精细地管理:

容量 capacity 元素 size 内存申请 对象构造 对象析构 内存释放

所以理解allocator,实际上是在帮助小朋友理解:

vector、STL 容器到底是怎么管理内存的。


十七、一个很重要的“坑”:不要混着用

下面这些组合是正确的:

int *p = new int; delete p;
int *p = new int[10]; delete[] p;
allocator<int> a; int *p = a.allocate(10); a.deallocate(p, 10);

但下面这些不要做:

int *p = new int[10]; delete p; // ❌

以及:

int *p = new int; delete[] p; // ❌

更不要:

allocator<int> a; int *p = a.allocate(10); delete[] p; // ❌

因为:

申请内存和释放内存的方法必须匹配。


十八、再送同学们一个“内存管理口诀”

可以把它背下来:

new 对 delete,new[] 对 delete[];

allocate 对 deallocate;

一个对象 delete,一组对象 delete[];

allocator 更底层,内存和对象可以分开管理。


十九、最后做一道小测试

看到下面的代码:

int *p1 = new int; int *p2 = new int[20]; allocator<int> a; int *p3 = a.allocate(30);

问:

p1怎么释放?

delete p1;

p2怎么释放?

delete[] p2;

p3怎么释放?

a.deallocate(p3, 30);

所以最后变成:

delete p1; delete[] p2; a.deallocate(p3, 30);

二十、给小学生真正要掌握的三个层次

这个知识点不要一上来就要求大家背很多规则,可以分成三个层次。

第一层:必须掌握 ⭐⭐⭐⭐⭐

new → delete new[] → delete[]

知道:

一个用delete,一组用delete[]


第二层:理解 ⭐⭐⭐⭐

知道:

new

不仅仅是申请内存,还会创建对象

而:

delete

不仅仅是释放内存,还会处理对象的销毁


第三层:拓展 ⭐⭐⭐

理解:

allocator

把:

“内存申请”

“对象创建/销毁”

进行了更加精细的分离。

这其实已经开始进入STL 容器底层实现的世界了。


最后用一张图彻底记住

C++ 动态内存 │ ┌───────────┼───────────┐ │ │ │ new T new T[n] allocator │ │ │ ↓ ↓ ↓ 一个对象 一组对象 原始内存 │ │ │ ↓ ↓ ↓ delete p delete[] p deallocate

而最核心的一句话是:

🧠deletedelete[]的区别,不是“删一个变量还是删很多变量”,而是它们必须分别匹配newnew[]allocator则进一步把“申请内存”和“创建对象”这两件事情拆开了。